take runDate of cron job as an input to the script which is being run - linux

I have written a cronjob which runs on daily basis.
#!/bin/sh
Z=$(cat /home/saurabh/scripts/2017-09-15)
echo "$Z"
Y="File Content $Z ,Done"
echo "$Y"
I have made an entry in crontab file to run this script on daily basis.
I want to take 2017-09-15 as a variable depending upon the date on which cron job is running. How can I do that ?

You can get the present date at the time of the cron run in your
specified format with date -I. Right now, that matches the string
in your Z.
#! /bin/sh
# Optionally put into temp var.
dt=$(date -I)
Z=$(cat /home/saurabh/scripts/$(date -I))
# or: Z=$(cat /home/saurabh/scripts/$dt)
echo "$Z"
...

Related

How to run a scrip if the time is matched with a time in another time zones

Currently, I am using cloud VMs to run my code and because of that I am assigned with a new VM that is in a different time zone. I want to run a bash script that runs a python script at 7:30 pm (Eastern time). From here I know how to run a bash script at a specific time, e.g., echo "ls -l" | at 07:00. From here I know how to get the current time of Eastern time, e.g., TZ=America/New_York date. Also, from here I know how to get only the time using date +%R.
I am a Python coder and tried my best to write a sudo code that shows what I am trying to accomplish as a bash script:
while true
do
Now=TZ=America/New_York date +%R
if [Now -eq 7:30pm]
then
python3 myfile.py
done
As you already know how to set the at command to execute a command
at the specified time, and how to convert the EST to the local time,
you can just combine them:
echo "python3 myfile.py" | at $(date -d "19:30 EST" +%R)
When you invoke the at command, it always warns
"commands will be executed using /bin/sh". It will matter only if we invoke
a bash specific command such as:
echo "shopt -s globstar; ls **" | at ..
which will fail.
In our case, the command python3 myfile.py will run with both
/bin/sh and /bin/bash then you do not worry about the warning.
date -d STRING interprets the STRING as a date/time representation
and prints the converted date/time in the specified format +%R.
If you want to send the output to a file, you can say:
echo "python3 myfile.py > /path/to/a/file" | at $(date -d "19:30 EST" +%R)
In order to output to the current terminal, first identify the terminal
with tty command:
$ tty
=> /dev/pts/0
Then redirect the output to the terminal with:
echo "python3 myfile.py > /dev/pts/0" | at $(date -d "19:30 EST" +%R)

Delete a newly created file using shell script after 5 minutes

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

Using SBATCH Job Name as a Variable in File Output

With SBATCH you can use the job-id in automatically generated output files using the following syntax with %j:
#!/bin/bash
# omitting some other sbatch commands here ...
#SBATCH -o slurm-%j.out-%N # name of the stdout, using the job number (%j) and the first node (%N)
#SBATCH -e slurm-%j.err-%N # name of the stderr, using job and first node values
I've been looking for a similar syntax for using the job-name instead of the job-id. Does anyone have a reference for what other slurm/sbatch values can be referenced in the %j style syntax?
In the newest versions of SLURM there is an option %x that represents job name.
See the "Changes in Slurm 17.02.1" section on the github:
https://github.com/SchedMD/slurm/blob/master/NEWS
However on many current clusters the slurm version is older than that and this option is not implemented. You can view the version of the slurm scheduler on your system:
sbatch --version
However there is a workaround.
You can create your own bash script, that can take a name as an argument, create a submission script that uses that name for the job name and output files and then submit it. For example,
You can create a script submit.sh:
#!/bin/bash
echo "#!/bin/bash" > jobscript.sh
echo "#SBATCH -o $1-%j.out-%N" >> jobscript.sh
echo "#SBATCH -e $1-%j.err-%N" >> jobscript.sh
echo "#SBATCH -J $1" >> jobscript.sh
#other echo commands with SBATCH options
echo "srun mycommand" >> jobscript.sh
#submit the job
sbatch jobscript.sh
And then execute it with an argument that correspond to the job name you want to give to your job:
bash ./submit.sh myJobName

Append new lines to cronjob's output log

Right now I append my php script's output to a logfile. Unfortunately it writes everything in one line. How do I need to change my cron command to append every execution log in a new line?
My current cronjob looks like this:
/usr/local/bin/php -q /home/username/public_html/forum/cron.php >> /home/username/cron.log 2>&1
Solved by adding echo "" as below:
/usr/local/bin/php -q /home/username/public_html/forum/cron.php >> /home/username/cron.log 2>&1; echo "" >> /home/username/cron.log
I know this post is old however I do not believe the approach above was the best solution.
The solution above will add a new line everytime the cronjob is run.
Now this is fine if after everytime the cronjob runs there is output.
However, if there is no output then echo "" >> /home/username/cron.log will print a new line into the cron.log.
I'd suggest adding "\n" to the php file where the output echoed. Then remove the echo "" >> /home/username/cron.log from the cronjob.
Eg:
echo "The cron job completed Successfully\n";

How to output the start and stop datetime of shell script (but no other log)?

I am still very new to shell scripting (bash)...but I have written my first one and it is running as expected.
What I am currently doing is writing to the log with sh name-of-script.sh >> /cron.log 2>&1. However this writes everything out. It was great for debugging but now I don't need that.
I now only want to see the start date and time along with the end date and time
I would still like to write to cron.log but just the dates as mentioned above But I can't seem to figure out how to do that. Can someone point me in the right direction to do this...either from within the script or similar to what I've done above?
A simple approach would be to add something like:
echo `date`: Myscript starts
to the top of your script and
echo `date`: Myscript ends
to the bottom and
echo `date`: Myscript exited because ...
wherever it exits with an error.
The backticks around date (not normal quotes) cause the output of the date command to be interpolated into the echo statement.
You could wrap this in functions and so forth to make it neater, or use date -u to print in UTC, but this should get you going.
You ask in the comments how you would avoid the rest of the output appearing.
One option would be to redirect the output and error of everything else in the script to /dev/null, by adding '>/dev/null 2>&1' to every line that output something, or otherwise silence them. EG
if fgrep myuser /etc/password ; then
dosomething
fi
could be written:
if fgrep myuser /etc/password >/dev/null 2>&1 ; then
dosomething
fi
though
if fgrep -q myuser /etc/password ; then
dosomething
fi
is more efficient in this case.
Another option would be to put the date wrapper in the crontab entry. Something like:
0 * * * * sh -c 'echo `date`: myscript starting ; /path/to/myscript >/dev/null 2>&1; echo `date`: myscript finished'
Lastly, you could use a subshell. Put the body of your script into a function, and then call that in a subshell with output redirected.
#!/bin/bash
do_it ()
{
... your script here ...
}
echo `date`: myscript starting
( do_it ) >/dev/null 2>&1
echo `date`: myscript finished
Try the following:
TMP=$(date); name-of-scipt.sh; echo "$TMP-$(date)"
or with formatted date
TMP=$(date +%Y%m%d.%H%M%S); name-of-scipt.sh; echo "$TMP-$(date +%Y%m%d.%H%M%S)"

Resources