2

I have a bash script. This bash script needs to be ran every 5 minutes so I created this code block:

#!/bin/bash
ulimit -n 600000
ulimit -u 600000
echo -e "This is another bash script to run mybashscript.sh"

# Lets create mycronscript.sh
echo "#!/bin/bash
ulimit -n 600000
ulimit -u 600000
while true; do
sleep 300
bash mybashscript.sh
done" >> mycronscript.sh
bash mycronscript.sh&

Whenever It runs itself after 5 minutes, the mybashscript.sh isn't running properly because ulimit settings aren't applied. How can I fix it?

5
  • How are you checking this? What is the expected behavior here? The subshell won't be able to affect other shells, are you expecting the ulimit builtin to have some sort of effect outside the shell it is running in?
    – terdon
    Apr 20, 2023 at 18:00
  • @terdon OP seems to have included a simplified example code while their actual script has more and a limit per shell might be needed ... At least that's what I understood as the example is actually only a sleep call, so nothing useful is expected from that ... Erikli, is this the case? or otherwise you might be just launching subshells with sleep calls and the ulimit is internally applied to each of those shells and will have no external effects on other shells.
    – Raffa
    Apr 20, 2023 at 18:12
  • You cannot increase either value as non-root in your script.
    – Cyrus
    Apr 20, 2023 at 18:13
  • @Raffa Yes. That is the case. I have a application(s) that needs a lot limit more than shell default provides. So I had to set them like this. PS: I have root access.
    – Erikli
    Apr 21, 2023 at 7:24
  • @terdon Since the application that I will be running to needs a lot ulimit to be ran, I can check it. If the application didn't start, then the ulimit values aren't applied properly.
    – Erikli
    Apr 21, 2023 at 7:25

1 Answer 1

5

There are two obvious issues with your code:

First, you need to use single quotes around the string after echo to prevent the shell from interpreting the ! in the shebang #!/bin/bash as the history expansion character which is expanded inside double quotes ... So it needs to look like this:

echo '#!/bin/bash
ulimit -n 600000
ulimit -u 600000
while true; do
sleep 300
bash mybashscript.sh
done' >> mycronscript.sh

You might not notice issues with that when run from inside a script in a non-interactive shell where history is not enabled by default versus when run from an interactive shell ... But, it might/will bite you back(e.g. it will automatically run the last command starting with /bin/bsh for example if you have previously run some script with /bin/bash scriptfile that command will be instantly run without asking for your confirmation at all) sometime soon e.g. when your shell settings/environment variables change to enable history in non-interactive shells.

I would, however, use better formatting mechanism alternatives for that with e.g. a Here Document like so:

cat > mycronscript.sh <<EOF
#!/bin/bash
ulimit -n 600000
ulimit -u 600000
while true; do
sleep 300
bash mybashscript.sh
done
EOF

or even the shell builtin printf(making use of its formatting capabilities) instead of echo.

Also, your use of the append operator >> might suggest that mycronscript.sh already has some lines/code and you're appending to it ... If this is the case then you'll end up with a messy unusable script ... If this is not the case, then use the > operator to overwrite the contents of the script file.

Second, you would need to run your script with elevated privileges i.e. sudo in order to increase the max user processes limit or the max open files limit ... etc. using ulimit above the hard limit ... So it needs to look like this:

sudo bash mainscript.sh

Notice: that if you use sudo on a script and send it to the background at the same time e.g.:

sudo bash mycronscript.sh &

you might need to bring that back to the foreground with fg in order to be able to enter the password for sudo or otherwise the script will be waiting for the password in the background and not executing without you noticing it ... So either run your main forground script with sudo as described above or you can login to a root shell with e.g. sudo -i then run your scripts there without sudo and be very careful as every command you run will run with root privileges.

I wouldn't be keen on using sudo inside scripts as well.

Also, please notice that ulimit is a shell builtin and it provides control over the resources available to processes started under the current shell it's run in and will have no effect on other external shells.

Also, notice that you can lower/increase the soft limit without root privileges using the -S option as long as it doesn't exceed the set hard limit ... like so:

ulimit -S -u {N}

where {N} is a number less than the hard limit ... You can print the hard limit for e.g. user processes with:

ulimit -H -u

or for all limits with:

ulimit -H -a

You can as well lower the hard limit without root privileges with e.g.:

ulimit -H -u {N}

or, as both -H and -S are the default when neither option is specified, with:

ulimit -u {N}

But, you can't raise it again without root privileges.

7
  • I have ran mycronscript.sh with sudo but still after a while, It just stops again. (If it stops then ulimit settings aren't applied)
    – Erikli
    Apr 21, 2023 at 7:26
  • @Erikli Then probably logging in to a root shell and running your scripts there might be what you want … Please see the description for how to do that in my answer.
    – Raffa
    Apr 21, 2023 at 8:19
  • still doesn't work.
    – Erikli
    Apr 21, 2023 at 10:02
  • @Erikli Are you sure your system's resources are enough for that large number of processes? ... Does your system freeze, become unresponsive or become very slow after you run your script?
    – Raffa
    Apr 21, 2023 at 11:07
  • No, not at all. If you have a somewhere I can contact with you I can show my script and what it does.
    – Erikli
    Apr 21, 2023 at 11:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .