How to schedule cron job every other week - cron

How to enable cron entry for bi-weekly basis (every other week) .
For example if cron runs on 05/05/2017(Friday) , It should run on 19/05/2017(Friday)

Execute the cron every week and test inside the file if do or not something.
For example:
<?php
if (date("W")%2 == 0) {
//do something
} else {
//wait
}
?>

This should run every friday:
0 0 1-31 1-12 5 someScript.sh
This will check if it's an odd week:
someScript.sh
#!/bin/sh
WEEK_OF_YEAR=`/bin/date +%V`
echo $WEEK_OF_YEAR
if [[ $(($WEEK_OF_YEAR % 2)) -eq 1 ]];
then
echo "DO SOMETHING"
fi

Related

Running multiple parallel sqlplus connections for a certain period of time in bash

I have this code that creates 20 parallel sqlplus instances, doing some queries and exits:
#!/bin/sh
for i in $(seq 1 20);
do
echo "CREATE TABLE table_$i (id NUMBER NOT NULL);
select * from table_$i;
! sleep 30
select * from table_$i;
! sleep 30
DROP TABLE table_$i;" | sqlplus system/password &
done
wait
I need to adjust this code if possible so it would run for an hour with the following conditions:
Always stay on 20 connections, if one sqlplus instance is closed (Finished it's process) another one should open, i need to maintain a certain amount of connections for X amount of time.
Is there anything i can add to this code that will achieve what i need?
For looping during an hour, see https://stackoverflow.com/a/22735757/3220113
runsql() {
i="$1"
end=$((SECONDS+3600))
SECONDS=0
while (( SECONDS < end )); do
# Do what you want.
echo "CREATE TABLE table_$i (id NUMBER NOT NULL);
select * from table_$i;
! sleep 30
select * from table_$i;
! sleep 30
DROP TABLE table_$i;" | sqlplus system/password
sleep 1 # precaution when sqlplus fails, maybe wrong password
done
}
for i in $(seq 1 20); do
runsql $i &
done
wait
Explanation:
The main loop at the bottom starts the function runsql 20 times in the background.
The function runsql could use $1 everywhere, I copy it to i for code that looks like the original.
SECONDS is a counter that is changed every second by the shell, so we do not need to call date.
3600 is an hour.
Inside (( .. )) you can do math without $ in front of variables.

Compare the days of the week in unix scripting

I want to compare the current day of the week and execute a set of statements depending on day.
to_day=$(date +%a)
if[ "$to_day" = "Sun" ]
then
echo "Today is sunday"
echo "First day of the week"
elif[ "$to_day" = "Mon" ]
then
echo "Today is monday"
echo "Second day of the week"
and so on...
I have tried the below if formats
if[$to_day = "Tue"]
if["$to_day" -eq "Tue"]
if["$to_day" == 'Tue']
if["$to_day" = 'Tue']
But the error is still present and it reads "if[ Tue = Tue ]:Command not fount ". I have tried the above with spaces after the braces also.
Make sure in your first line is:
#!/bin/bash
and if it is in your code then make sure if: /bin and /usr/bin or /usr/local/bin directories are in you path, because all commands are here. You can check with:
$ echo $PATH
and you will get a similar answer:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/home/vivekgite/bin
but if you don't have those paths, you can add theirs with:
$ export PATH=$PATH:/bin:/usr/local/bin

Crontab setting - execute script every 55 minutes

I found a interesting thing during creation of my crontab setting.
I used this command:
crontab -e
and fill this line:
*/55 * * * * export DISPLAY=:0 && /home/user/Documents/script.sh $2>/dev/null
My idea was create scheduler, which start script.sh every 55 minutes.
But this script is execute in this times (for example):
08:55, 09:00, 09:05, 09:55, 10:00, 10:05, ...
and I don't know why.
Can someone explain me that?
Replace the script like this and it should work.
*/5 * * * * [ $(( $(date +%s) / 60 % 55 )) -eq 0 ] && export DISPLAY=:0 && /home/user/Documents/script.sh $2>/dev/null
minute-hour-day-month-year
* any value
, value list separator
- range of values
/ step values
Another option is a self-replicating 'at' job. Only advantage over cron is that it is less obvious, and also if you needed it to kick off not every X minutes, but X minutes after the last job completed. So your script will just contain a line to create a new 'at' job before it exits. Something like:
echo "/full/path/to/my/script > /root/myScript.at.log" | at now + X minutes
so every 5 minutes it will do this:
number of seconds elapsed since 1. 1. 1970 will divided by 60 = how many minutes
echo $(date +%s)
1476201056 ... second
echo $(( $(date +%s) / 60 ))
24603351 ... minutes
after that it will use modulo on count of minutes
When result of modulo is 0, it will send TRUE value.
And it is a typical logical AND
[ $((......)) -eq 0 ] && export DISPLAY.. && .../script.sh
Thank you.
It is really helpful :)

Bash, run multiple commands simultaneously, wait for N to finish before spawning more

Alright, so I've tried gnu parallel and there's some quirks about getting that to work that makes it not possible for me to use.
Ultimately I'd love to just be able to do something like this:
for modelplot in /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs
do
for regionplot in $mregions
do
opengrads -bclx "${modelplot}.gs $regionplot ${plotimage} ${date} ${run} ${gribfile} ${modelplot}" && wait -n
done
done
But I can't seem to find a way to limit the spawning of background processes to a specific number. Someone mentioned doing:
for i in {1..10}; do echo "${i} & (( count ++ > 5 )) && wait -n; done
Should do it, but I can't really verify if it is working that way. It seems like it just spawns them all instantly. I'm assuming the output in terminal of that should be: echo 1, echo 2, echo 3, echo 4, echo 5. Then echo 6, echo 7, echo 8, echo 9, echo 10.
I'm just trying to spawn, say 5, iterations of a loop, wait for those to finish and then spawn the next 5, wait for those to finish, spawn the next 5, etc until the loop is done.
Each time you start a background job, increment a count. When that count reaches 5 (or whatever), wait for all background jobs to complete, then reset the count to 0 and resume starting background jobs.
p_count=0
for modelplot in /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs; do
for regionplot in $mregions; do
opengrads -bclx "${modelplot}.gs $regionplot ${plotimage} ${date} ${run} ${gribfile} ${modelplot}" &
if (( ++p_count == 5 )); then
wait
p_count=0
fi
done
done
done
It is surprisingly tricky to keep exactly 5, rather than at most 5, jobs running in the background in shell. (wait -n lets you know when a job has finished, but not how many have finished.) To keep the machine busy, a tool like xargs or parallel is more appropriate.
From your comments it is pretty unclear what you want.
But using the {= =} construct you can get almost anything in the arguments.
Append .gs only on the first run:
parallel echo {}'{= if($job->seq() == 1) { $_ = ".gs" } else { $_="" } =}' ::: a b c
Append .gs only on the last run:
parallel echo {}'{= if($job->seq() == $Global::JobQueue->total_jobs() ) { $_ = ".gs" } else { $_="" } =}' ::: a b c
Disregarding the comments and looking only at the loop in the question the solution is:
parallel --header : opengrads -bclx "{modelplot}.gs {regionplot} ${plotimage} ${date} ${run} ${gribfile} {modelplot}" ::: modelplot /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs ::: regionplot $mregions

Write a bash script that accepts a time duration as arguments?

I'm looking for a bash script that can parse a time duration.
If three arguments are given, they represent hours, minutes, and seconds. If two arguments are given, they represent minutes and seconds, with the hours zero.
What about the following:
#!/bin/bash
h=0
if [ "$#" -ge 3 ]
then
h=$1
shift
fi
sec=$((3600*$h+60*$1+$2))
echo "The total number of seconds is $sec"
Since the question does not specify what you aim to do with the given time, the program calculates the total number of seconds. Furthermore perhaps it is useful to do a check if at least two arguments are given.
The script uses the shift operation, the shift makes makes $1 := $2; $2 := $3, etc. In other words, the first argument is processed, and then you "pretend" it never existed.
By default you set h to zero, and only if the number of arguments is greater than or equal to 3, it will set h.
This is a more or less general solution for that type of task. Sorry, if it is a monkeycode, but I think it is sufficient:
gettime() {
params=(
years months weeks days hours minutes seconds
)
for i in `seq ${#params}`; do
param_i=$((${#params} - i + 1)) # reversed params index
[ $i -le $# ] && {
eval "local ${params[$param_i]}=\$$(($# - i + 1))"
} || {
eval "local ${params[$param_i]}=0"
}
eval "echo ${params[$param_i]} '==' \$${params[$param_i]}" # debug output
done
}
Here's the sample output:
$ gettime 3 4 5 6 7
seconds == 7
minutes == 6
hours == 5
days == 4
weeks == 3
months == 0
years == 0
Note, that the shell you are using must be not only support POSIX standards, but also arrays.
First Argument: $1
Second Argument: $2
Third Argument: $3
and so on...
Example:
bash-2.05a$ ./parseDuration.sh 13 25 25
13 hours and 25 minutes and 25 seconds
bash-2.05a$ cat ./parseDuration.sh
#!/bin/bash
echo "$1 hours and $2 minutes and $3 seconds"

Resources