I'm building a backup script to run on Ubuntu.
backup-all.sh file:
echo "bootstrap"
/home2/backup/bootstrap/backup.sh
BOOTSTRAP_STATUS=$([ "$?" == 0 ] && echo "OK" || echo "** FAIL **")
echo "sv2"
/home2/backup/sv2/backup.sh
SV2_STATUS=$([ "$?" == 0 ] && echo "OK" || echo "** FAIL **")
if [ "$BOOTSTRAP_STATUS" == "OK" ] && [ "$SV2_STATUS" == "OK" ] ; then
TITULO="Backup OK"
else
TITULO="Backup !FAILED!"
fi
(
echo "Backup status"
echo "-------------"
echo "BOOTSTRAP_STATUS = $BOOTSTRAP_STATUS"
echo "SV2_STATUS = $SV2_STATUS"
echo "-------------"
) | mail -s "${TITULO}" "my#mail.org"
The backup.sh files ends with:
exit 0 # for success; OR:
exit 1 # for errors + send mail with log file
* backup.sh files contains rsync and mysql backup.
When the script returns 1 (error), it will also send me an e-mail telling me that's something is wrong and all steps are recorded on a log file.
** I have email calls. One for overview, and one for each "server" which gets errors.
So, If I run manually,
./backup-all.sh
Everything is nice. I receive just one mail with title "Backup OK".
If I wait cron to run the job, I receive just one mail with title "Backup !FAILED!", even though I didn't receive errors details and the log files are OK.
crontab -e
0 0 * * * /home2/backup/backup-all.sh
So, what cron job does with the condition/exit values of my scripts?
to debug, log stdout and error to log file:
0 0 * * * /home2/backup/backup-all.sh > /tmp/debug.log 2>&1
A few possibilities, cron does not have proper env by default or by design:
rsync and mysqldump not in cron env
add #!/usr/bin/bash to your bash script
Related
The parallel execution is working properly as expected. But i need to get the states of each file. Here I need to check it by using the if condition. This is just a sample and i have many scenarios like this in my code.
I'm a beginner at #help shell scripts & linux but actually i love linux now.
I'm expecting an alternative method or a help to resolve this. Thank you everyone.
( echo $FILE_PATH/import_csv_location_data_into_hive.sh; echo $FILE_PATH/import_csv_order_data_into_hive.sh; echo $FILE_PATH/import_csv_order_with_delivery_info_into_hive.sh; ) | parallel bash
wait
IMPORTED_LOCATIONS_STATUS=$? IMPORTED_ORDERS_STATUS=$? IMPORTED_ORDERS_WITH_DELIVERY_INFO_STATUS=$?
if [[ "$IMPORTED_LOCATIONS_STATUS" == "0" && "$IMPORTED_ORDERS_STATUS" == "0" && "$IMPORTED_ORDERS_WITH_DELIVERY_INFO_STATUS" == "0" ]];
then
echo "COMPLETED."
exit 0
else
STATUS="FAILED."
exit 1
fi
Sample code
enter image description here
(echo Your-Special-Header; \
echo whoami; \
echo cat nothere \
) | parallel --header : --results all.csv bash -c
The file nothere does not exist. Here is the csv output:
Seq,Host,Starttime,JobRuntime,Send,Receive,Exitval,Signal,Command,Your-Special-Header,Stdout,Stderr
1,:,1662823208.481,0.001,0,5,0,0,"bash -c whoami",whoami,"root
",
2,:,1662823208.481,0.003,0,0,1,0,"bash -c cat\ nothere","cat nothere",,"cat: nothere: No such file or directory
"
The 7th column is Exitval.
If you only need to know if all finished with no errors:
(
echo $FILE_PATH/import_csv_location_data_into_hive.sh;
echo $FILE_PATH/import_csv_order_data_into_hive.sh;
echo $FILE_PATH/import_csv_order_with_delivery_info_into_hive.sh;
) | parallel bash
if [[ "$?" == "0" ]]; then
echo "COMPLETED."
exit 0
else
STATUS="FAILED."
exit 1
fi
Shorter, but less readable IMO:
(
echo $FILE_PATH/import_csv_location_data_into_hive.sh;
echo $FILE_PATH/import_csv_order_data_into_hive.sh;
echo $FILE_PATH/import_csv_order_with_delivery_info_into_hive.sh;
) | if parallel bash ; then
echo "COMPLETED."
exit 0
else
STATUS="FAILED."
exit 1
fi
I am trying to build a bash script to run a web server. I need the script to show output of web server in console until specific word appears on the console indicating either the server initialization completed successfully or some error occurs.
I was able to show the console output until timeout occurs:
#!/bin/bash
(exec /opt/aspnetcore-runtime-3.0.0-linux-x64/dotnet /opt/app/Launcher.dll &) | (timeout --foreground 6 cat; cat > /dev/null &)
If an error happens earlier than 6 seconds, then the web server stopped and the control goes back to the terminal, which is the desired behavior.
However, if the web server initialization was successfully completed in 2 seconds, the user must wait for another 4 seconds until the script finishes. I want to return the control back to terminal once some phrase (e.g. SUCCESS INIT!) appear on the console.
On surface, replacing the current wait ('cat') with a custom loop that will exit when 'SUCCESS INIT!' is found will address the problem
Such a loop can be implemented with
while read x && echo "$x" && [ "$x" != "SUCCESS INIT!" ] ; do : ; done
And the combined command
(Launch-command &) | (timeout --foreground 6 sh -c 'while read x && echo "$x" && [ "$x" != "SUCCESS INIT!" ] ; do : ; done' ; cat > /dev/null &)
Not very elegant. If you can, put the 'timeout ... while ...' in a separate script. I did not test, but it should work:
#! /bin/bash
# wait-line.sh
timeout --foreground "$1" sh -c "while read x && echo "$x" && [ "$x" != "$2" ] ; do : done "
cat > /dev/null
And then the original command line will look like
( Launch-command ... & ) | ( wait-line.sh 6 "SUCCESS INIT!" &)
A bash script executes several commands.
After each command, how to:
if success: show a custom message in the console and append it to a log file
if error: show the error message in the console, append error message to the log file and resume the entire script
Here is where I am:
log_file="log.txt"
output() {
echo $#
echo $# 2>&1 >> $log_file;
if [ $# -eq 0 ]
then
exit 1
fi
}
and then after each command:
if [ $? -eq 0 ]
then
output "Custom message"
else
output $?
fi
Which makes lots of repetitions…
You could create a "run" function to limit repetition:
run()
{
message="$1"
shift
eval "$*"
if [ $? -eq 0 ]; then
output "$message"
else
output $?
fi
}
And simply prefix every command with:
run "message" "command"
The command only needs to be quoted if it contains shell meta-expressions.
Here's a way to accomplish that; after each command to be tracked, add this line:
rc="$?"; if [ "$rc" -eq 0 ]; then echo "Custom message" 2>&1 | tee -a /folder/log; else echo "$rc" 2>&1 | tee -a /folder/log; fi
The following command will give you the exit status of your last run command.
$?
e.g lets say you executed "ls" command , after that if you execute the following
echo $?
you will see the exit status as 0. which means successful . An Non-zero exit status means failure.
You can use this in some sort of if else in your shell script and based on the exit value do whatever you need to do.
I have the following variables set in a script.
SU="/bin/su -s /bin/sh
WSO2_SCRIPT="JAVA_HOME=$JAVA_HOME /opt/autopilot/wso2is/bin/wso2server.sh"
WSO2_USER=autoplt
This part of the script is of concern:
if [ "$RETVAL" -eq "0" ]; then
if [ "$(whoami)" != "${WSO2_USER}" ]; then
$SU - $WSO2_USER -c "${WSO2_SCRIPT} start" >> ${WSO2_LOG} 2>&1 || RETVAL="4"
else
${WSO2_SCRIPT} start >> ${WSO2_LOG} 2>&1 || RETVAL="4"
fi
fi
If I am root, then the following command gets executed:
/bin/su -s /bin/sh - autoplt -c 'JAVA_HOME=/usr/java/latest /opt/autopilot/wso2is/bin/wso2server.sh start'
and
RETVAL
will get evaluated to 0.
When I am user autoplt, the following command gets executed:
JAVA_HOME=/usr/java/latest /opt/autopilot/wso2is/bin/wso2server.sh start
However
RETVAL
will get evaluated to 4?
Are they not the same commands? Shouldn't RETVAL be 0 in each case?
The command gets executed successfully when I run it in the shell as autoplt user.
Therefore is there something wrong with the way I have written it?
the double pipe || used in lines :
$SU - $WSO2_USER -c "${WSO2_SCRIPT} start" >> ${WSO2_LOG} 2>&1 || RETVAL="4"
${WSO2_SCRIPT} start >> ${WSO2_LOG} 2>&1 || RETVAL="4"
means if the first command succeed, then the second will not be executed
It means when running as root, it succeed then no change to RETVAL
and as a user, if fails so change RETVAL to 4
Can any one let me know how to re-run the process automatically again if it gets dies. Below is my code which i have tired but it is giving me an error :
Edited Code :
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
if [ $commandpid -gt 0 ]
then
echo -16 > /proc/$commandpid/oom_adj
echo -1000 > /proc/$commandpid/oom_score_adj
fi
while [ true ]
do
echo "PID $commandpid"
if [ ps -p $commandpid > /dev/null ]
then
echo "[$(date)] :Process is already running with PID $commandpid"
else
echo "[$(date)] :Process is not running"
/data/local/command 1200 &
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
fi
sleep 10
done
I have updated the code but still with the above code multiple process id i am getting. Dose it mean my else part code is keep executing? If yes the what changes i need to do to stop it?
Can please any one help me ?
To repeatedly run a command, regardless of exit status:
while :; do command; done
To repeatedly run a command until a successful exit:
until command; do :; done