Can't run a shell script every 24 hours - shell

I have written a shell script that runs some commands. I have added a logic to run this script once every 24 hours. But it runs once and then doesn't run.
The script is as below:
#!/bin/bash
while true; do
cd /home/ubuntu/;
DATE=`date '+%Y-%m-%d'`;
aws s3 cp --recursive "/home/ubuntu/" s3://bucket_name/$DATE/;
rm -r -f ./*;
# sleep 24 hours
sleep $((24 * 60 * 60))
done
Why does it not run once every 24 hours ? I do not get any errors when the script runs. The copy takes about 10 mins.

The good practice is to protect your script againt multirunning.
In this case, you can be sure that only 1 instance is running.
#!/bin/bash
LOCKFILE=/tmp/block_file
if ( set -o noclobber; echo "$$" > "$LOCKFILE") 2> /dev/null;
then
trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT
while true; do
cd /home/ubuntu/;
DATE=`date '+%Y-%m-%d'`;
aws s3 cp --recursive "/home/ubuntu/" s3://bucket_name/$DATE/;
rm -r -f ./*;
# sleep 24 hours
sleep $((24 * 60 * 60))
done
rm -f "$LOCKFILE"
trap - INT TERM EXIT
else
echo "Warning. Script is already running!"
echo "Block by PID $(cat $LOCKFILE) ."
exit
fi
You can run a script immune to hangups.
nohup is a UNIX utility that runs the specified command ignoring communication loss signals (SIGHUP). Thus, the script will continue to work in the background even after the user logs out.
nohup ./yourscript.sh
The created file /tmp/block_file will safe runned script against multirunning. To complete it press ctrl+c or run kill -11 pidofyourscript in terminal, in this way /tmp/block_file will be deleted.
The output of script puts on file nohup.out.
To run in background (preferred way):
nohup ./yourscript.sh &

Your script is probably killed due to inactivity, or when you exit the shell. The proper way to do this is use cron, as #Christian.K mentioned. See https://help.ubuntu.com/community/CronHowto

Related

Linux cron job dont want to run my script

So i have been trying to make a auto reboot script, most of it works, but when it comes down to my if else statement i dont think it get ran when i run the script via cron job
#!/bin/sh
screen -x modded
sleep 2
screen -S modded -X stuff "say restarting in 1 minute"
screen -S modded -X eval "stuff \015"
# [...]
screen -wipe
sleep 2
screen -ls | awk '/\.modded\t/ {print strtonum($1)}' > pid/kill.pid
sleep 1
PIDFile="/home/Minecraft/direwolf20-server1.12/pid/kill.pid"
File=`stat -c %s pid/kill.pid`
if [ $File -lt 1 ];then
rm pid/kill.pid
sleep 2
sh ./start
else
sleep 2
kill -9 $(<"$PIDFile")
sleep 2
rm pid/kill.pid
sleep 2
screen -wipe
sleep 2
sh ./start
fi
when i run the script my self it works fine
Two options:
Ensure that the script is marked as executable.
When creating the cron entry specify the shell just before the script.
eg.
0 */12 * * * /bin/bash /home/foo/script.sh

process not starting completely, when called inside crontab

I have a script( let us call it watcher) which checks for a particular process if it's not running the watcher will start the process through a script.
I run this watcher in crontab at every minute. Now the problem is that it's not working in crontab but working if I run the watcher directly from the command line.
suppose the watcher start a script file called serverA.
ServerA code
echo -n "Starting $NAME: "
# start network server
start-stop-daemon --start --background --make-pidfile \
--pidfile $net_server_pidfile --startas /bin/bash -- -c "exec $angel $net_server \
-c $conf_file --lora-eui $lora_eui --lora-hw-1 $lora_hw --lora-prod-1 $lora_id \
--lora-path $run_dir --db $conf_db \
--noconsole >> $net_server_log 2>&1"
sleep 2
# start packet forwarder
/usr/sbin/start-stop-daemon --chdir $run_dir/1 --start --background --make-pidfile \
--pidfile $pkt_fwd_pidfile --exec $angel -- $pkt_fwd
renice -n -20 -p $(pgrep lora-network-se)
renice -n -20 -p $(pgrep $(basename $pkt_fwd))
echo "OK"
Now if i run watcher from directly the serverA will echo output Starting something then after sometime it continues with OK at the end.
But in crontab logs i dont see the OK, because of which the service never completes and serverA never starts.
watcher.sh
else
echo "$(date) do something, no packet forwader runnig"
exec /etc/init.d/lora-network-server start
fi
I think that you need to check difference of run time environments based terminal or not.
Firstly Check the lora-network-server whether depend on shell environments, such as JAVA_HOME or PATH (e.g. can execute the binary without absolute path of binary).
If it has different setting, it make same shell environments.
For exmaple, how to diff between cron env and runtime env.
runtime
$ env | tee ./runtime.output
cron
$ crontab <<EOF
* * * * * /bin/env > /path/to/cron.output 2>&1
EOF
Above cron output will create after 1 minute, and remove the cront after test.
you can check the variables onto cron.output and runtime.output
I hope this will help you.
Cron runs with a mostly empty environment. Are you setting all necessary environment variables in your scripts?

Simple daemon process in Ubuntu

I want to start a simple daemon process in Ubuntu, which will write the current time to log file every 5 seconds.
start-stop-daemon --start --user root --make-pidfile --pidfile /home/manjesh/test.pid --exec /home/manjesh/simplescript.sh
simplescript.sh
#!/bin/bash
echo $(date)" SNMP Monitoring and Log aggregator service " >> /home/manjesh/log.txt
while true
do
echo $(date) >> /home/dcae/snmp-service/log
sleep 5
done
When I execute the command it says "No such file or directory even if the file do exist"
Any help will be appreciated. Thanks.
The way I would do this is to use a cron job that triggers every minute and calls a script that writes the time every 5 seconds, like this:
Cron:
* * * * * /usr/local/bin/script >/dev/null 2>&1
Script:
#!/bin/bash
mkdir -p /home/dcae/snmp-service/
i="0"
while [ $i -lt 12 ]
do
echo $(date) >> /home/dcae/snmp-service/log
i=$[$i+1]
sleep 5
done
The problem was I had created a file in Windows and moved to Ubuntu, and there was a formatting problem
-bash: ./my_script: /bin/bash^M: bad interpreter: No such file or directory

How to make bash script execute command at regular intervals

I'm working on a bash script that will run for appoximately 30 minutes at a time. I've got it running stable as far as that part goes. I've been looking for a way to make it fire certain commands at inervals of every 3 minutes while running. I've not had any luck, so I turn to those of you that may know more about bash than I.
Any suggestions?
Here is what I have in mind of doing.
START=$(date +%s);
while read LINE <&3; do
END=$(date +%s);
if [[ $(($END-$START)) > 180 || $(($END-$START)) == 180 ]]
then
$START=$(date +%s);
run command
fi
done
Add a cron job to make it run every 3 minutes.
*/3 * * * * /path/to/script
What about the watch command?? (https://unix.stackexchange.com/questions/10646/repeat-a-unix-command-every-x-seconds-forever)
(Second answer on here: Run command every second)
You can run a loop in the background:
{ while /bin/true; do some_command; sleep 180; done; } &
loop_pid=$!
Then before the main script exits, kill the background loop:
kill $loop_pid
You can also call the same script from same script.
$ cat script.sh
#!/bin/bash
# commands
# commands
sleep 1800
sh $0

Bash script to watch execution time of other scripts

I have a main script which run all the scripts in a folder.
#!/bin/bash
for each in /some_folder/*.sh
do
bash $each
done;
I want to know if execution of one of them lasts too long (more than N seconds). For example execution of script such as:
#!/bin/bash
ping -c 10000 google.com
will lasts very long, and I want my main script to e-mail me after N second.
All I can do now is to run all scripts with #timeout N option but it stops them!
Is it possible to E-mail me and not to stop execution of script?
Try this :
#!/bin/bash
# max seconds before mail alert
MAX_SECONDS=3600
# running the command in the background and get the pid
command_that_takes_a_long_time & _pid=$!
sleep $MAX_SECONDS
# if the pid is alive...
if kill &>/dev/null -0 $_pid; then
mail -s "script $0 takes more than $MAX_SECONDS" user#domain.tld < /dev/null
fi
We run the command in the background, then sleep for MAX_SECONDS in // and alert by email if the process takes more than what is permitted.
Finally, with your specific requirements :
#!/bin/bash
MAX_SECONDS=3600
alerter(){
bash "$1" & _pid=$!
sleep $MAX_SECONDS
if kill &>/dev/null -0 $_pid; then
mail -s "$2 takes more than $MAX_SECONDS" user#domain.tld < /dev/null
fi
}
for each in /some_folder/*.sh; do
alerter "$each" &
wait $_pid # remove this line if you wou'd like to run all scripts in //
done
You can do something like this:
( sleep 10 ; echo 'Takes a while' | sendmail myself#example.com ) &
email_pid=$!
bash $each
kill $email_pid
The first command is run in a subshell in the background. It first sleeps a while, then sends email. If the script $each finishes before the sleep expires, the subshell is killed without sending email.

Resources