Delete a newly created file using shell script after 5 minutes - linux

I am writing a shell script where I create a file ABC.txt in a path /path/to/ABC/ABC.txt.
Now I at the end of the script, I want to schedule a cron job to delete this file after 5 minutes (just once, not recurring).
I cannot ad sleep of 5 minutes in this script as it is being used by multiple users on server for multiple paths/files. And 5 minutes after the user executes this script the corresponding file.txt from respective path should get deleted.
What I read from a cronjob is you can trigger a script using crontab -e and then providing periodic notation of job and path to script H/5 * * * * /bin/sh /path/to/ABC/ABC.txt.
Can someone tell me how to schedule such functionality using cron. If there is a better way to do this please suggest.

Using at command:
#!/usr/bin/env bash
script_path="$(realpath -s -- "$0")"
# start script
...
# end script
echo "rm -- \"$script_path\"" | at "now + 5 minutes"
Using background process with sleep:
#!/usr/bin/env bash
script_path="$(realpath -s -- "$0")"
# start script
...
# end script
( sleep 300 && rm -- "$script_path" ) &
Using parent selfdestruct process:
Write a little script selfdestruct that looks like:
#!/usr/bin/env bash
dt="$1"; shift
"$#"
( sleep "$dt" && rm -- "$1" ) &
and run your script with
$ selfdestruct 300 /path/to/script arg1 arg2 arg3

Related

All the process logs from container

I have a container, it starts with shell script.sh such as:
FROM bash:4.4
COPY script.sh /
COPY process.sh /
CMD ["bash", "/script.sh"]
Here is script.sh:
#!/bin/sh
sh process.sh &
for i in {1..10000}
do
sleep 1
echo "Looping ... number $i"
done
It starts another process by running process.sh script.
Here is the process.sh script:
#!/bin/sh
for i in {1..10}
do
sleep 1
echo "I am from child process ... number $i"
done
Now I want to see all the stdout message. If I go to the directory like /var/lib/docker/containers/container_sha:
I see something like below:
I am from child process ... number {1..10}
Looping ... number 1
Looping ... number 2
Looping ... number 3
Looping ... number 4
Looping ... number 5
Looping ... number 6
.....
It is obvious that, I see only the script.sh output but not process.sh
Why is that? And how can i get all the logs?
Note: docker logs containerName does the same.
{1..10} is bash syntax, and does not expand to anything in sh. So the loop runs once, with the word {1..10} (literally).
You can run process.sh with bash instead of sh
Or if you want/need sh, you could either:
Use a counter:
while c=$((c+1)); [ "$c" -le 10 ]; do
Use a program like seq (not POSIX):
for i in $(seq 10); do
Iterate arguments passed from bash like:
sh process.sh {1..10} &
and in process.sh:
for i do

Run all shell scripts in folder

I have many .sh scripts in a single folder and would like to run them one after another. A single script can be executed as:
bash wget-some_long_number.sh -H
Assume my directory is /dat/dat1/files
How can I run bash wget-some_long_number.sh -H one after another?
I understand something in these lines should work:
for i in *.sh;...do ....; done
Use this:
for f in *.sh; do
bash "$f"
done
If you want to stop the whole execution when a script fails:
for f in *.sh; do
bash "$f" || break # execute successfully or break
# Or more explicitly: if this execution fails, then stop the `for`:
# if ! bash "$f"; then break; fi
done
It you want to run, e.g., x1.sh, x2.sh, ..., x10.sh:
for i in `seq 1 10`; do
bash "x$i.sh"
done
To preserve exit code of failed script (responding to #VespaQQ):
#!/bin/bash
set -e
for f in *.sh; do
bash "$f"
done
There is a much simpler way, you can use the run-parts command which will execute all scripts in the folder:
run-parts /path/to/folder
I ran into this problem where I couldn't use loops and run-parts works with cron.
Answer:
foo () {
bash -H $1
#echo $1
#cat $1
}
cd /dat/dat1/files #change directory
export -f foo #export foo
parallel foo ::: *.sh #equivalent to putting a & in between each script
You use GNU parallel, this executes everything in the directory, with the added buff of it happening at a lot faster rate. Not to mention it isn't just with script execution, you could put any command in the function and it'll work.

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

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.

Bash script manual execute run normally but not with crontab

Hello i have a script like this one:
#!/usr/bin/bash
ARSIP=/apps/bea/scripts/arsip
CURDIR=/apps/bea/scripts
OUTDIR=/apps/bea/scripts/out
DIRLOG=/apps/bea/jboss-6.0.0/server/default/log
LISTFILE=$CURDIR/tmp/file.$$
DATE=`perl -e 'use POSIX; print strftime "%Y-%m-%d", localtime time-86400;'`
JAVACMD=/apps/bea/jdk1.6.0_26/bin/sparcv9/java
HR=00
for (( c=0; c<24; c++ ))
do
echo $DATE $HR
$JAVACMD -jar LatencyCounter.jar LatencyCounter.xml $DATE $HR
sleep 1
cd $OUTDIR
mv btw_120-180.txt btw_120-180-$DATE-$HR.txt
mv btw_180-360.txt btw_180-360-$DATE-$HR.txt
mv btw_60-120.txt btw_60-120-$DATE-$HR.txt
mv failed_to_deliver.txt failed_to_deliver-$DATE-$HR.txt
mv gt_360.txt gt_360-$DATE-$HR.txt
mv out.log out-$DATE-$HR.log
cd -
let HR=10#$HR+1
HR=$(printf %02d $HR);
done
cd $OUTDIR
tar -cf latency-$DATE.tar btw*-$DATE-*.txt gt*$DATE*.txt out-$DATE-*.log
sleep 300
gzip latency-$DATE.tar
sleep 300
/apps/bea/scripts/summaryLatency.sh
sleep 300
rm -f btw* failed* gt* out*
#mv latency-$DATE.tar.gz ../$ARSIP
cd -
It basically execute jar files in same directory as this script and then tar the result, gzip it and execute another bash file then delete all of the previous collected files. The problem is i need this script to run daily and i use crontab to do that. It still return empty tar file but if i execute it manually it works well..I also have other 4 scripts running in crontab and they work good..i still can't figure out what is the main reason of this phenomena
thank you
I'll take a stab: your script is run by /bin/sh instead of /bin/bash.
Try explicitly running it with bash at the cron entry, like this:
* * * * * /bin/bash /your/script
I'm guessing that when you execute $JAVACMD -jar LatencyCounter.jar LatencyCounter.xml $DATE $HR, you're not in the directory containing LatencyCounter.jar. You might want to cd $CURDIR before you enter the for loop.

Shell Script For Process Monitoring

This
#!/bin/bash
if [ `ps -ef | grep "91.34.124.35" | grep -v grep | wc -l` -eq 0 ]; then sh home/asfd.sh; fi
or this?
ps -ef | grep "91\.34\.124\.35" | grep -v grep > /dev/null
if [ "$?" -ne "0" ]
then
sh home/asfd.sh
else
echo "Process is running fine"
fi
Hello, how can I write a shell script that looks in running processes and if there isn't a process name CONTAINING 91.34.124.35 then execute a file in a certain place and I want to make this run every 30 seconds in a continuous loop, I think there was a sleep command.
you can't use cron since on the implementation I know the smallest unit is one minute. You can use sleep but then your process will always be running (with cron it will started every time).
To use sleep just
while true ; do
if ! pgrep -f '91\.34\.124\.35' > /dev/null ; then
sh /home/asfd.sh
fi
sleep 30
done
If your pgrep has the option -q to suppress output (as on BSD) you can also use pgrep -q without redirecting the output to /dev/null
First of all, you should be able to reduce your script to simply
if ! pgrep "91\.34\.124\.35" > /dev/null; then ./your_script.sh; fi
To run this every 30 seconds via cron (because cron only runs every minute) you need 2 entries - one to run the command, another to delay for 30 seconds before running the same command again. For example:
* * * * * root if ! pgrep "91\.34\.124\.35" > /dev/null; then ./your_script.sh; fi
* * * * * root sleep 30; if ! pgrep "91\.34\.124\.35" > /dev/null; then ./your_script.sh; fi
To make this cleaner, you might be able to first store the command in a variable and use it for both entries. (I haven't tested this).
CHECK_COMMAND="if ! pgrep '91\.34\.124\.35' > /dev/null; then ./your_script.sh; fi"
* * * * * root eval "$CHECK_COMMAND"
* * * * * root sleep 30; eval "$CHECK_COMMAND"
p.s. The above assumes you're adding that to /etc/crontab. To use it in a user's crontab (crontab -e) simply leave out the username (root) before the command.
I would suggest using watch:
watch -n 30 launch_my_script_if_process_is_dead.sh
Either way is fine, you can save it in a .sh file and add it to the crontab to run every 30 seconds. Let me know if you want to know how to use crontab.
Try this:
if ps -ef | grep "91\.34\.124\.35" | grep -v grep > /dev/null
then
sh home/asfd.sh
else
echo "Process is running fine"
fi
No need to use test. if itself will examine the exit code.
You can save your script in file name, myscript.sh
then you can run your script through cron,
*/30 * * * * /full/path/for/myscript.sh
or you can use while
# cat script1.sh
#!/bin/bash
while true; do /bin/sh /full/path/for/myscript.sh ; sleep 30; done &
# ./script1.sh
Thanks.
I have found deamonizing critical scripts very effective.
http://cr.yp.to/daemontools.html
You can use monit for this task. See docu. It is available on most linux distributions and has a straightforward config. Find some examples in this post
For your app it will look something like
check process myprocessname
matching "91\.34\.124\.35"
start program = "/home/asfd.sh"
stop program = "/home/dfsa.sh"
If monit is not available on your platform you can use supervisord.
I also found this question very similar Repeat command automatically in Linux. It suggests to use watch.
Use cron for the "loop every 30 seconds" part.

Resources