cron - one script works while the other doesn't - bash

I am on Archlinux and I am trying to force a cron application to execute my script. So I installed package fcron and ran it's daemon first and then I added fcrontab which looks like this:
* * * * * /home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript
Ok so this is where it gets tricky. This script will execute if it's contents looks like this:
#!/bin/bash
PATH=/usr/bin
touch ~/test-002.txt
But it won't execute if it's contents look like this:
#!/bin/bash
PATH=/usr/bin
acpi -b | awk -F'[,:%]' '{print $2, $3}' | {
read -r status capacity
if [ "$status" = Discharging -a "$capacity" -lt 5 ]; then
logger "Critical battery threshold"
systemctl hibernate
fi
}
Why is that? Even the Archlinux Wiki says it should work, but I assume it is wrong - I only changed #!/bin/bash and added PATH=/usr/bin. Script works on its own...
EDIT:
So I edited my script to look like below and it doesn't work.
#!/bin/sh
SHELL=/bin/sh
/usr/bin/acpi -b | /usr/bin/awk -F'[,:%]' '{print $2, $3}' | (
read -r status capacity
if [ "$status" = Discharging ] && [ "$capacity" -lt 50 ]; then
/usr/bin/systemctl hibernate
fi
)
If I run
[ziga#ziga-laptop hibernate]$ run-parts ~/Dropbox/workspace/operacijski/archlinux/hibernate/ -v
run-parts: executing /home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate//hibernatescript
My PC hibernates, but again cron doesn't hibernate my PC using the exact same script. I also tried fcron and it doesn't work although daemon is fully running and fcrontab is set. Again this works for any simpler scripts while it wont work for this one.
Here are some info:
[ziga#ziga-laptop ~]$ systemctl status fcron.service
● fcron.service - fcron periodical command scheduler
Loaded: loaded (/usr/lib/systemd/system/fcron.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2016-06-21 10:39:48 CEST; 58min ago
Process: 419 ExecStart=/usr/bin/fcron (code=exited, status=0/SUCCESS)
Main PID: 423 (fcron)
Tasks: 1 (limit: 512)
CGroup: /system.slice/fcron.service
└─423 /usr/bin/fcron
Jun 21 11:34:00 ziga-laptop fcron[12833]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:34:02 ziga-laptop fcron[12833]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:35:00 ziga-laptop fcron[13021]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:35:02 ziga-laptop fcron[13021]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:36:00 ziga-laptop fcron[13210]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:36:02 ziga-laptop fcron[13210]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:37:00 ziga-laptop fcron[13407]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:37:02 ziga-laptop fcron[13407]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:38:00 ziga-laptop fcron[13599]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
Jun 21 11:38:02 ziga-laptop fcron[13599]: Job '/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescrip
[ziga#ziga-laptop ~]$ fcrontab -l
2016-06-21 11:38:48 INFO listing ziga's fcrontab
* * * * * /home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript
[ziga#ziga-laptop ~]$ cat /home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript
#!/bin/sh
SHELL=/bin/sh
/usr/bin/acpi -b | /usr/bin/awk -F'[,:%]' '{print $2, $3}' | (
read -r status capacity
if [ "$status" = Discharging ] && [ "$capacity" -lt 50 ]; then
/usr/bin/systemctl hibernate
fi
)
[ziga#ziga-laptop ~]$ ls -l /home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/
total 16
-rwxrwxrwx 1 ziga users 214 Jun 21 08:46 hibernatescript
-rw-rw-rw- 1 ziga users 2832 Jun 21 00:24 README.txt
[ziga#ziga-laptop ~]$ groups ziga
lp audio bumblebee users
[ziga#ziga-laptop ~]$

Related

SSH into multiple servers and compare timestamps of each server

I need to add the timestamp of all remote servers as part of output and check & compare whether the timestamp is the same or not,
I am able to print the machine IP and date.
#!/bin/bash
all_ip=(192.168.1.121 192.168.1.122 192.168.1.123)
for ip_addr in "${all_ip[#]}"; do
aws_ip=$"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
date=date
sshpass -p "password" ssh root#$ip_addr "$aws_ip & $date"
echo "==================================================="
done
Getting Output as :
Wed 27 Jul 2022 05:48:15 AM PDT
192.168.1.121
===================================================
Wed Jul 27 05:48:15 PDT 2022
192.168.1.122
===================================================
Wed Jul 27 05:48:15 PDT 2022
192.168.1.123
===================================================
How to check whether the timestamp ( ignoring seconds ) of all machines is the same or not ,
eg: (Wed 27 Jul 2022 05:48:15 || Wed 27 Jul 2022 05:48:15 || Wed 27 Jul 2022 05:48:15)
Expected Output:
|| Time are in sync on all machines || # if in sync
|| Time are not in sync on all machines || # if not sync
Wed 27 Jul 2022 05:48:15 AM PDT
192.168.1.121
===================================================
Wed Jul 27 05:48:15 PDT 2022
192.168.1.122
===================================================
Wed Jul 27 05:48:15 PDT 2022
192.168.1.123
===================================================
How to check whether the time ( ignoring seconds )
tmpdir=$(mktemp -d)
trap 'rm -r "$tmpdir"' EXIT
for ip in "${allips[#]}"; do
# Do N connections, in paralllel, each one writes to a separate file.
sshpass -p "password" ssh root#"$ip" "date +%Y-%m-%d_%H:%M" > "$tmpdir/$ip.txt" &
done
wait
times=$(
for i in "$tmpdir"/*.txt; do
# print filename with file contents.
echo "$i $(<$i)"
done |
# Sort them on second column
sort -k2 |
# Uniq on second field
uniq -f 2
)
echo "$times"
timeslines=$(wc -l <<<"$times")
if ((timeslines == 1)); then
echo "YAY! minutes on all servers the same"
fi
First, you may adjust your "date" command as folow in order to exclude the seconds:
date +%Y-%m-%d_%H:%M
Then, simply grep your output and validate that all the timestamps are identical. You may dump in a temporary file or any other way.
Ex:
grep [aPatternSpecificToTheLinewithTheDate] [yourTemporaryFile] | sort | uniq | wc -l
If the result is 1, it means that all the timestamps are identical.
However you will have to deal with the corner case where the minute shift while you are fetching the time form all your servers.

For loop with if statements isn't working as expected in bash

It only prints the "else" statement for everything but I know for a fact the files exist that it's looking for. I've tried adapting some of the other answers but I thought this should definitely work.
Does anyone know what's wrong with my syntax?
# Contents of script
for ID_SAMPLE in $(cut -f1 metadata.tsv | tail -n +2);
do if [ -f ./output/${ID_SAMPLE} ]; then
echo Skipping ${ID_SAMPLE};
else
echo Processing ${ID_SAMPLE};
fi
done
Additional information
# Output directory
(base) -bash-4.1$ ls -lhS output/
total 170K
drwxr-xr-x 8 jespinoz tigr 185 Jan 3 16:16 ERR1701760
drwxr-xr-x 8 jespinoz tigr 185 Jan 17 18:03 ERR315863
drwxr-xr-x 8 jespinoz tigr 185 Jan 16 23:23 ERR599042
drwxr-xr-x 8 jespinoz tigr 185 Jan 17 00:10 ERR599072
drwxr-xr-x 8 jespinoz tigr 185 Jan 16 13:00 ERR599078
# Example of inputs
(base) -bash-4.1$ cut -f1 metadata.tsv | tail -n +2 | head -n 10
ERR1701760
ERR599078
ERR599079
ERR599070
ERR599071
ERR599072
ERR599073
ERR599074
ERR599075
ERR599076
# Output of script
(base) -bash-4.1$ bash test.sh | head -n 10
Processing ERR1701760
Processing ERR599078
Processing ERR599079
Processing ERR599070
Processing ERR599071
Processing ERR599072
Processing ERR599073
Processing ERR599074
Processing ERR599075
Processing ERR599076
# Checking a directory
(base) -bash-4.1$ ls -l ./output/ERR1701760
total 294
drwxr-xr-x 2 jespinoz tigr 386 Jan 15 21:00 checkpoints
drwxr-xr-x 2 jespinoz tigr 0 Jan 10 01:36 tmp
-f is for checking whether the name is a file, but all your names are directories. Use -d to check that.
if [ -d "./output/$ID_SAMPLE" ]
then
If you want to check whether the name exists with any type, use -e.

Restart Apache if average server load past minute is higher than X

I wrote a shell script and added it to my cron. It's supposed to run every minute and check for the average server load, past 1 minute, and if it's over 40 it should log the load, date and then restart Apache httpd. Here is my script:
#!/bin/bash
LOGFILE=/home/user/public_html/domain.com/cron/restart.log
function float_to_int() {
echo $1 | cut -d. -f1
}
check=$(uptime | awk -F' *,? *' '{print $12}')
now=$(date)
checkk=$(float_to_int $check)
if [[ $checkk > 40 ]]; then
echo $now $checkk >> $LOGFILE 2>&1
/usr/bin/systemctl restart httpd.service
fi
If I look at the log file I see the following:
Wed Jul 3 20:02:01 EDT 2019 70
Wed Jul 3 23:03:01 EDT 2019 43
Wed Jul 3 23:12:01 EDT 2019 9
Wed Jul 3 23:13:01 EDT 2019 7
Wed Jul 3 23:14:01 EDT 2019 6
Wed Jul 3 23:15:02 EDT 2019 5
Wed Jul 3 23:16:01 EDT 2019 5
Something is clearly wrong as it should only log and restart Apache if the load is over 40 but as you can see from the logs the load was 9, 7, 6, 5 and 5. Could someone point me in the right direction?
From man bash, section CONDITIONAL EXPRESSIONS (emphasis mine) :
string1 > string2
True if string1 sorts after string2 lexicographically.
You will either want to use [['s -gt operator, or use arithmetic evaluation instead of [[ :
if (( chekk > 40 )); then
Here's one in GNU awk (GNU awk due to strftime()):
awk '
$1 > 0.4 { # interval above 0.4
logfile="./log.txt" # my logpath, change it
print strftime("%c"), $1 >> logfile # date and load to log
cmd="/usr/bin/systemctl restart httpd.service" # command to use for restarting
if((ret=(cmd|getline res)) !=0 ) # store return value and result
print "failed: " ret # if failed
else
print "success"
}' /proc/loadavg # getting load avg from /proc

I need to run the same script multiple times in parallel with log management

I need to run the same script multiple times in parallel with log management of each script execution
I need an optimal method please?
script name : script.sh
logs : log_execution1.log log_execution2.log ...
or
logs : log_execution-PID.log log_execution-PID.log ...
thanks
This can be done around a loop:
$ ntimes=42
$ for i in $(seq 1 $ntimes) ; do (script.sh > log_execution$i.log &) ; done
I did it like that :
it's work fine now.
while [ -e file.dat ]
do
./a.ksh
sleep 5
done
file : a.ksh
#!/bin/ksh
echo "Hello StackOverFlow" > log_execution-$$.log
exit 0
Result
-rw-r--r-- 1 aai aai 22 Apr 19 11:11 log_execution-27310.log
-rw-r--r-- 1 aai aai 0 Apr 19 11:11 log_execution-26005.log
-rw-r--r-- 1 aai aai 22 Apr 19 11:11 log_execution-27327.log
thank you for your help

Bash script doesn't cater to new line, appends text to current line

I have a script that redirects stdout to a log file after running command xyz. I tried doing this in the console:
xyz > temp.log &
and when I look at temp.log its perfect as I expect it to be. But when I run the above command inside a script temp.log is just one big line of all stdout. How do I make it print the same as running it from console? I have shown the logs below.
Running xyz > temp.log & from console
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 18
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 6
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 3
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 2
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 19
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 11
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 1
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 12
/source_id:int64/(Green-aeon-GlobalMillennium-Spout): 3
Running from within the script
ESC[?1049hESC[1;48rESC(BESC[mESC[4lESC[?7hESC[HESC[2JEvery 5.0s: Green-aeon-GlobalMillennium-SpoutESC[1;178HTue Feb 12 11:36:08 2013ESC[3;1H/source_id:36/sch_event:1797777 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[4d/source_id:36/sch_event:1797779 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[5d/source_id:36/sch_event:1797781 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[6d/source_id:36/sch_event:1797783 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[7d/source_id:36/sch_event:1797785 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[8d/source_id:36/sch_event:1797787 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST` 2013^MESC[9d/source_id:36/sch_event:1797789 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC[10d/source_id:36/sch_event:1797791 for Green-aeon-GlobalMillennium-Spout at Tue Feb 12 11:16:41 CST 2013^MESC
This is the script
#!/bin/sh
die () {
echo >&2 "$#"
exit 1
}
[ "$#" -ge 4 ] || die "usage notification_stats <table_name> <listener_name> <time_interval> <time_to_run>"
echo $3 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $3 provided for time_interval"
echo $4 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $4 provided for time_to_run"
watch -n $3 xyz -v $1 $2 > notify.log &
$my_pid = $!
sleep $4
kill -9 $my_pid
Don't use watch. It's meant for interactive display, not to run a program repeatedly.
You can use
#!/bin/bash
while (( SECONDS <= $4 ))
do
xyz -v $1 $2
sleep $3
done > notify.log
instead

Resources