Shell script to run two scripts when server load is above 20 - linux

I need a script that I can run on a cron every 5 minutes that will check if server load is above 20 and if it is it will run two scripts.
#!/bin/bash
EXECUTE_ON_AVERAGE="15" # if cpu load average for last 60 secs is
# greater or equal to this value, execute script
# change it to whatever you want :-)
while true; do
if [ $(echo "$(uptime | cut -d " " -f 13 | cut -d "," -f 1) >= $EXECUTE_ON_AVERAGE" | bc) = 1 ]; then
sudo s-
./opt/tomcat-latest/shutdown.sh
./opt/tomcat-latest/startup.sh
else
echo "do nothing"
fi
sleep 60
done
I then chmod +x the file.
When I run it I get this:
./script.sh: line 10: ./opt/tomcat-latest/shutdown.sh: No such file or directory
./script.sh: line 11: ./opt/tomcat-latest/startup.sh: No such file or directory

From the looks of it, your script is trying to execute the two scripts from the current working directory into opt/tomcat-latest/ -- which doesn't exist. You should confirm the full file paths for the two shell scripts and then use that instead of the current path.
Also, I'd recommend that you create a cron to do this task. Here's some documentation about the crontab. https://www.gnu.org/software/mcron/manual/html_node/Crontab-file.html

check the permission to execute the files shutdown.sh and startup.sh
Is sudo -s not sudo s-
And I recommend to put a sleep (seconds)
sudo -s /opt/tomcat-latest/shutdown.sh
sleep 15
sudo -s /opt/tomcat-latest/startup.sh
Or better
sudo -s /opt/tomcat-latest/shutdown.sh && sudo -s /opt/tomcat-latest/startup.sh
The startup.sh will executed only if shutdown.sh was executed with success.

Related

Bash - Dump script works when running manually but not by crontab [duplicate]

This question already has answers here:
Difference between sh and Bash
(11 answers)
Closed 3 months ago.
For security purposes, I have been writing a script that daily create dump, and manage them for some daily dumps, and some monthly dumps. I have a weird issue that I can clearly understand. When I run the script above manually ./save_db.sh evrything works. But I did add this in crontab of the same user (which is not root).
cd /home/debian/script && sh save_db.sh
The script is this:
#!/bin/bash
nom_dump="$(date +%H:%M-%d%m%y)"
mysqldump -u debian --all-databases | gzip -c > /home/debian/bdd_dump/journalier/"$nom_dump".sql.gz
sauv_mensuelle="$(date +%d)"
if [ $sauv_mensuelle == "01" ]
then
cp "$nom_dump".sql.gz /home/debian/bdd_dump/mensuel
compte_sauv="$(ls /home/debian/bdd_dump/mensuel | wc -l)"
if (( $compte_sauv > 6 ))
then
clean_mensuel="$(ls -t /home/debian/bdd_dump/mensuel/ | tail -1)"
rm /home/debian/bdd_dump/mensuel/"$clean_mensuel"
fi
fi
compte_semaine="$(ls /home/debian/bdd_dump/journalier/ | wc -l)"
if (( $compte_semaine > 7 ))
then
clean_daily="$(ls -t /home/debian/bdd_dump/journalier/ | tail -1)"
rm /home/debian/bdd_dump/journalier/"$clean_daily"
fi
When crontab runs it, the last part is not working as intended, but I can't know why. Dumps older than 7 days are not being removed
Thanks :)
The way you are calling this script:
cd /home/debian/script && sh save_db.sh
Is environment dependent. Chmod +x your script and replace the call in crontab with
/path/to/script/my-script-name.sh
You only need one shell process to run, not two, and you don't need to change your working directory to invoke it.

How to run script multiple times and after every execution of command to wait until the device is ready to execute again?

I have this bash script:
#!/bin/bash
rm /etc/stress.txt
cat /dev/smd10 | tee /etc/stress.txt &
for ((i=0; i< 1000; i++))
do
echo -e "\nRun number: $i\n"
#wait untill module restart and bee ready for next restart
dmesg | grep ERROR
echo -e 'AT+CFUN=1,1\r\n' > /dev/smd10
echo -e "\nADB device booted successfully\n"
done
I want to restart module 1000 times using this script.
Module is like android device witch has linux inside it. But I use Windows.
AT+CFUN=1,1 - reset
When I push script, after every restart I need a command which will wait module and start up again and execute script 1000 times. Then I do pull in .txt file and save all output content.
Which command should I use?
I try commands like wait, sleep, watch, adb wait-for-device, ps aux | grep... Nothing works.
Can someone help me with this?
I find the solution. This is how my script actually looks:
#!/bin/bash
cat /dev/smd10 &
TEST=$(cat /etc/output.txt)
RESTART_TIMES=1000
if [[ $TEST != $RESTART_TIMES ]]
then
echo $((TEST+1)) > /etc/output.txt
dmesg
echo -e 'AT+CFUN=1,1\r\n' > /dev/smd10
fi
These are the steps that you need to do:
adb push /path/to/your/script /etc/init.d
cd /etc
cat outputfile.txt - make an output file and write inside file 0 ( echo 0 > output.txt )
cd init.d
ls - you should see rc5.d
cd .. then cd rc5.d - go inside
ln -s ../init.d/yourscript.sh S99yourscript.sh
ls - you should see S99yourscript.sh
cd .. return to init.d directory
chmod +x yourscript.sh - add permision to your script
./yourscript.sh

assign output of command to variable in bash script run by root cron

I have been trying to write a script that will backup my minecraft server but only run if I am not actively on the server. The way i am trying to do this is by parsing the output of top and grepping the process name and getting the CPU usage. When I am not on the server the usage is usually less than 10. The server is run as a service so in order to bring it down before the backup and to bring it back up I need to use systemctl stop and systemctl start in so it need to be run as root. This is the script I have:
#!/bin/bash
PATH="$PATH:/usr/bin:/bin"
CPU=`/usr/bin/top -b n1 | /usr/bin/grep bedrock_server | /usr/bin/awk '{ print $9 }' | /usr/bin/cut -d . -f 1`
DATE=`date '+\%m-\%d'`
dirname="/home/brandon/bedrock-backups/$DATE"
if [ "$CPU" -lt 20 ];
then
systemctl stop bedrock-server.service && \
mkdir -p $dirname && chown brandon $dirname && chmod 777 $dirname && \
cd /home/brandon && \
tar -czf $dirname/bedrock-backup.tar bedrock/ && \
chown brandon $dirname/bedrock-backup.tar && chmod 777 $dirname/bedrock-backup.tar && \
echo "Backup Completed Successfully" && \
systemctl start bedrock-server.service
else
echo "Backup terminated due to server activity" && \
exit
fi
The issue seems to be that the output of the top command and all the subsequent parsing does not get assigned to CPU so the script errors out at if [ "$CPU" -lt 20 ] with the error integer expression expected. I tried to run the script in cron's env by adding the line env > ~/cronenv to root's crontab and have it run once then use env - `cat ~/cronenv` /bin/sh to get into crons environment. I run
CPU=`top -b n1 | grep bedrock_server | awk '{ print $9 }' | cut -d . -f 1`
and it works. I tried again as a cron job and I get the same error. Then I read that full paths to commands should be used inside cron so I added /usr/bin to the commands as seen above.
I've tried using #!/bin/sh as well as #!/bin/bash for the shebang. The crontab entry is as follows :
# m h dom mon dow command
SHELL=/bin/bash
PATH="$PATH:/usr/bin:/bin"
27 22 * * * /bin/bash /home/brandon/bin/scripts/backup-bedrock
#* * * * * env > ~/cronenv
I can even run the full script in the cronenv but not scheduled as a cron job.
I do not know what else to try or what I am doing wrong, hoping someone can help me.
Thanks!
Also this is on Ubuntu 20.04 if that matters

Start a Pythonscript in a Screen session

i am currently working on a little bash script to start a .py file in a Screen session and could use help.
I have these 2 Files:
test.py (located at /home/developer/Test/):
import os
print("test")
os.system("ping -c 5 www.google.de>>/home/developer/Test/test.log")
test.sh (located at /home/developer/):
#!/bin/bash
Status="NULL"
if ! screen -list | grep -q "foo";
then
Status="not running"
else
Status="running"
fi
echo "Status: $Status"
read -p "Press [Enter] key to start/stop."
if [[ $Status == "running" ]]
then
screen -S foo -p 0 -X quit
echo "Stopped Executing"
elif [[ $Staus == "not running" ]]
then
screen -dmS foo sh
screen -S foo -X python /home/developer/Test/test.py
echo "Created new Instance"
else
exit 1
fi
It works as intendet until it has to start the python script aka. this line:
screen -S foo -X python /home/developer/Test/test.py
when running it in my normal shell i get:
test
sh: 1: cannot create /home/developer/Test/test.log: Permission denied
MY Questions:
I understand the cause of the Permission denied case (works with sudo) but how do i give Permissions and more interestingly, to whom do i give the Permissions to? (python? | screen? | myuser?)
Is the line to create a new instance in which the script runs correct like that?
Can u think of a better way to execute a python script which has to run night and day but is start and stoppable and doesn't block the shell?
To answer your questions:
You should not need to use sudo at all if the proper user/group is set on the scripts.
$ chmod 644 <user> <group> <script name>
The line creating the new instance does not look correct, it should be more like:
screen -S foo -d -m /usr/bin/python /home/Developer/Test/test.py
While using full path to the python exec; remove useless preceding line: screen -dmS foo sh
Screen is more than adequte to prefer such tasks.
Other problems in your script:
Add a shebang to the python script (eg. #!/usr/bin/python)
Typo on line 20 of test.sh: should be $Status, not $Staus
You may need to initially create test.log before executing your script (eg. touch test.log)

TERM environment variable not set

I have a file.sh with this, when run show : TERM environment variable not set.
smbmount //172.16.44.9/APPS/Interfas/HERRAM/sc5 /mnt/siscont5 -o
iocharset=utf8,username=backup,password=backup2011,r
if [ -f /mnt/siscont5/HER.TXT ]; then
echo "No puedo actualizar ahora"
umount /mnt/siscont5
else
if [ ! -f /home/emni/siscont5/S5.TXT ]; then
echo "Puedo actualizar... "
touch /home/emni/siscont5/HER.TXT
touch /mnt/siscont5/SC5.TXT
mv -f /home/emni/siscont5/CCORPOSD.DBF /mnt/siscont5
mv -f /home/emni/siscont5/CCTRASD.DBF /mnt/siscont5
rm /mnt/siscont5/SC5.TXT
rm /home/emni/siscont5/HER.TXT
echo "La actualizacion ha sido realizada..."
else
echo "No puedo actualizar ahora: Interfaz exportando..."
fi
fi
umount /mnt/siscont5
echo "/mnt/siscont5 desmontada..."
You can see if it's really not set. Run the command set | grep TERM.
If not, you can set it like that:
export TERM=xterm
Using a terminal command i.e. "clear", in a script called from cron (no terminal) will trigger this error message. In your particular script, the smbmount command expects a terminal in which case the work-arounds above are appropriate.
You've answered the question with this statement:
Cron calls this .sh every 2 minutes
Cron does not run in a terminal, so why would you expect one to be set?
The most common reason for getting this error message is because the script attempts to source the user's .profile which does not check that it's running in a terminal before doing something tty related. Workarounds include using a shebang line like:
#!/bin/bash -p
Which causes the sourcing of system-level profile scripts which (one hopes) does not attempt to do anything too silly and will have guards around code that depends on being run from a terminal.
If this is the entirety of the script, then the TERM error is coming from something other than the plain content of the script.
You can replace :
export TERM=xterm
with :
export TERM=linux
It works even in kernel with virgin system.
SOLVED: On Debian 10 by adding "EXPORT TERM=xterm" on the Script executed by CRONTAB (root) but executed as www-data.
$ crontab -e
*/15 * * * * /bin/su - www-data -s /bin/bash -c '/usr/local/bin/todos.sh'
FILE=/usr/local/bin/todos.sh
#!/bin/bash -p
export TERM=xterm && cd /var/www/dokuwiki/data/pages && clear && grep -r -h '|(TO-DO)' > /var/www/todos.txt && chmod 664 /var/www/todos.txt && chown www-data:www-data /var/www/todos.txt
If you are using the Docker PowerShell image set the environment variable for the terminal like this with the -e flag
docker run -i -e "TERM=xterm" mcr.microsoft.com/powershell

Resources