Bash Script can run php script manually but cannot work in Cron - bash

I have a bash script like this:
#!/bin/bash
log_file=/home/michael/bash/test.log
checkalive=checkalive.php
#declare
needRestart=0
#Check checkalive.php
is_checkalive=`ps aux | grep -v grep| grep -v "$0" | grep $checkalive| wc -l | awk '{print $1}'`
if [ $is_checkalive != "0" ] ;
then
checkaliveId=$(ps -ef | grep $checkalive | grep -v 'grep' | awk '{ printf $2 }')
echo "Service $checkalive is running. $checkaliveId"
else
echo "$checkalive OFF"
needRestart=1
fi
#NEED needRestart
if [ $needRestart == "1" ];
then
#START SERVICE
echo "Restarting services..."
/usr/bin/php5.6 /home/michael/bash/$checkalive >/dev/null 2>&1 &
echo "$checkalive..."
echo `date '+%Y-%m-%d %H:%M:%S'` " Start /home/michael/bash/$checkalive" >> $log_file
fi
I can run it manually but when I try to run it in Cron, it doesn't work for some reasons. Apparently the command:
/usr/bin/php5.6 /home/michael/bash/$checkalive >/dev/null 2>&1 &
does not work.
All of file permissions are already set to executable. Any advice?
Thank you

You have run into one of cron's most common mistakes, trying to use it like an arbitrary shell script. Cron is not a shell script and you can't do everything you can do in one, like dereferencing variables or setting arbitrary new variables.
I suggest you replace your values into the cron line and avoid usage of variables
/usr/bin/php5.6 /home/michael/bash/checkalive.php >/dev/null 2>&1 &
Also, consider removing the trailing & as it is not necessary.

Related

heredoc failing when piped into ssh

I am trying to do commands via ssh using a heredoc. when I use the 'EOF' style:
result=$(ssh $quiet -T ${G_IPAddressBase}${G_TGP} <<- 'EOF'
set pid=`ps -ef | grep TestPatterns | egrep -v 'grep|tail|vi|csh' | gawk '{print $2}'`
if ( "$pid" != "" ) then
echo "TestPatterns ($pid) terminated"
kill $pid
else
echo "TestPatterns down already"
endif
EOF
)
everything works as excepted because the $ and qrave marks are not expanded out.
But if I want to include local variables and use \ to stop the variable from being resolved, the \ does not stop the $ variable from resolving as expected.
result=$(ssh $quiet -T ${G_IPAddressBase}${G_TGP} <<- EOF
set pid=\`ps -ef | grep $mytaskName | grep '\/bin\/bash' | gawk '{print \$2}'\`
if ( "\$pid" == "" ) then
echo "ERROR: $mytaskName cored"
else
if ( -f "$mytaskLogpath" ) then
set agent1Done=1
else
echo "ERROR: $mytaskName didn't make a report file"
endif
endif
EOF
)
The pid is being set to blank because its looks like this on the remote side:
set pid=`ps -ef | grep TestPatterns | egrep -v 'grep|tail|vi|csh' | gawk '{print }'`
Everything that I have read says this should not be happening. If I cat << EOF > /tmp/command.csh the heredoc to a file the commands match what I expect on the remote box and work as expected.
This script is in bash, but the default shell is tcsh and that's what the remote is running so its not because the csh commands are running in a bash window on the remote login.
Any ideas what I am doing wrong?

Why is exit my status valid in command line but not within bash script? (Bash)

There are a few layers here, so bear with me.
My docker-container ssh -c"echo 'YAY!'; exit 25;" command executes echo 'YAY!'; exit 25; in my docker container. It returns:
YAY
error: message=YAY!
, code=25
I need to know if the command within the container was successful, so I append the following to the command:
docker-container ssh -c"echo 'YAY!'; exit 25;" >&1 2>/tmp/stderr; cat /tmp/stderr | grep 'code=' | cut -d'=' -f2 | { read exitStatus; echo $exitStatus; }
This sends the stderr to /tmp/stderr and, with the echo $exitStatus returns:
YAY!
25
So, this is exactly what I want. I want the $exitStatus saved to a variable. My problem is, I am placing this into a bash script (GIT pre-commit) and when this exact code is executed, the exit status is null.
Here is my bash script:
# .git/hooks/pre-commit
if [ -z ${DOCKER_MOUNT+x} ];
then
docker-container ssh -c"echo 'YAY!'; exit 25;" >&1 2>/tmp/stderr; cat /tmp/stderr | grep 'code=' | cut -d'=' -f2 | { read exitStatus; echo $exitStatus; }
exit $exitStatus;
else
echo "Container detected!"
fi;
That's because you're setting the variable in a pipeline. Each command in the pipeline is run in a subshell, and when the subshell exits the variable are no longer available.
bash allows you to run the pipeline's last command in the current shell, but you also have to turn off job control
An example
# default bash
$ echo foo | { read x; echo x=$x; } ; echo x=$x
x=foo
x=
# with "lastpipe" configuration
$ set +m; shopt -s lastpipe
$ echo foo | { read x; echo x=$x; } ; echo x=$x
x=foo
x=foo
Add set +m; shopt -s lastpipe to your script and you should be good.
And as Charles comments, there are more efficient ways to do it. Like this:
source <(docker-container ssh -c "echo 'YAY!'; exit 25;" 2>&1 1>/dev/null | awk -F= '/code=/ {print "exitStatus=" $2}')
echo $exitStatus

A script to find all the users who are executing a specific program

I've written the bash script (searchuser) which should display all the users who are executing a specific program or a script (at least a bash script). But when searching for scripts fails because the command the SO is executing is something like bash scriptname.
This script acts parsing the ps command output, it search for all the occurrences of the specified program name, extracts the user and the program name, verifies if the program name is that we're searching for and if it's it displays the relevant information (in this case the user name and the program name, might be better to output also the PID, but that is quite simple). The verification is accomplished to reject all lines containing program names which contain the name of the program but they're not the program we are searching for; if we're searching gedit we don't desire to find sgedit or gedits.
Other issues I've are:
I would like to avoid the use of a tmp file.
I would like to be not tied to GNU extensions.
The script has to be executed as:
root# searchuser programname <invio>
The script searchuser is the following:
#!/bin/bash
i=0
search=$1
tmp=`mktemp`
ps -aux | tr -s ' ' | grep "$search" > $tmp
while read fileline
do
user=`echo "$fileline" | cut -f1 -d' '`
prg=`echo "$fileline" | cut -f11 -d' '`
prg=`basename "$prg"`
if [ "$prg" = "$search" ]; then
echo "$user - $prg"
i=`expr $i + 1`
fi
done < $tmp
if [ $i = 0 ]; then
echo "No users are executing $search"
fi
rm $tmp
exit $i
Have you suggestion about to solve these issues?
One approach might looks like such:
IFS=$'\n' read -r -d '' -a pids < <(pgrep -x -- "$1"; printf '\0')
if (( ! ${#pids[#]} )); then
echo "No users are executing $1"
fi
for pid in "${pids[#]}"; do
# build a more accurate command line than the one ps emits
args=( )
while IFS= read -r -d '' arg; do
args+=( "$arg" )
done </proc/"$pid"/cmdline
(( ${#args[#]} )) || continue # exited while we were running
printf -v cmdline_str '%q ' "${args[#]}"
user=$(stat --format=%U /proc/"$pid") || continue # exited while we were running
printf '%q - %s\n' "$user" "${cmdline_str% }"
done
Unlike the output from ps, which doesn't distinguish between ./command "some argument" and ./command "some" "argument", this will emit output which correctly shows the arguments run by each user, with quoting which will re-run the given command correctly.
What about:
ps -e -o user,comm | egrep "^[^ ]+ +$1$" | cut -d' ' -f1 | sort -u
* Addendum *
This statement:
ps -e -o user,pid,comm | egrep "^\s*\S+\s+\S+\s*$1$" | while read a b; do echo $a; done | sort | uniq -c
or this one:
ps -e -o user,pid,comm | egrep "^\s*\S+\s+\S+\s*sleep$" | xargs -L1 echo | cut -d ' ' -f1 | sort | uniq -c
shows the number of process instances by user.

shell script not working through cron but manually

I'm using below command in a shell script:
echo "1" > log.txt
if [ `ifconfig eth0 | grep 'inet addr' | cut -d ":" -f 2 |
awk {'print $1'}` = 'ipaddress' ] && [ `whoami` = 'userid' ]; then
echo "2" >> log.txt
crontab -l > Cron.txt
echo "3" >> log.txt
fi
The script runs fine when run manually but when scheduled through cron, it
stucks at this IF.
cron entry: 31 11 * * * /home/abc/cron_backup.sh
Output in log.txt Manual run: prints 1,2,3 in log.txt through
cron: prints 1 in log.txt
I would suggest to put as first line of your script the command interpreter line #! to make sure that sh will run it
after that, have you consider to use double bracket syntax [[ ]]?
#!/bin/sh
echo "1" > log.txt
if [[ `ifconfig eth0 | grep 'inet addr' | cut -d ":" -f 2 |
awk {'print $1'}` = 'ipaddress' ]] && [[ `whoami` = 'userid' ]]; then
echo "2" >> log.txt
crontab -l > Cron.txt
echo "3" >> log.txt
fi
The problem could be with the ifconfig, grep, cut awk and whoami calls. When you run it from the command line you have your profile, which has your PATH setting.
When it is run from cron, it does not have your profile. If you modify your PATH variable to point to the location of these programs then you wouldn't have that change when run from cron.
Try putting in the full path for the each of the commands and see it that makes any difference when run from cron.

execute conky with a cron job and bash

for my script in bash, I'd like to start conky if it's not running and pick a random wallpaper
#! /bin/bash
## dependances : randomize-lines
# otherwise wont work with cron
export DISPLAY=0
while read line ; do
echo $line | grep -vqe "^#"
if [ $? -eq 0 ]; then export $line; fi
done < ~/.dbus/session-bus/$(cat /var/lib/dbus/machine-id)-$DISPLAY
# random background
pathToImage="$HOME/Images/wallpaper/"
img="`find $pathToImage -name \*.jpg | rl | tail -n 1`"
/usr/bin/gconftool -t str -s /desktop/gnome/background/picture_filename $img
# test if conky is running
if ps ax | grep -v grep | grep conky > /dev/null
then
echo "conky running"
else
echo "conky is not running"
conky
fi
if I try to run the script within a terminal
$ ~/script/wallpaper/random-background.sh
conky is not running
Conky: can't open display: 0
if I put the test before the DISPLAY=0, it'll works in a terminal but not with cron
thank you
I think that should be
export DISPLAY=:0
but that won't work for
~/.dbus/session-bus/$(cat /var/lib/dbus/machine-id)-$DISPLAY
but you could change that to
~/.dbus/session-bus/$(cat /var/lib/dbus/machine-id)-0
You missed a ":":
export DISPLAY=:0

Resources