Creating script to report system suspend or awake is not running? - linux

Here is the code that should output to a file when system goes into SUSPEND or AWAKES:
(this code is in /etc/pm/sleep.d)
(also had to make the file executable: sudo chmod +x sleep_mode)
(when running from the command line, the "suspend script" is written to the file.
(but when I suspend the computer or awaken the computer... nothing is written to file.)
(16.04 LTS)
#!/bin/bash
# general entry
echo "suspend script"
echo "%suspend script" >> /tmp/suspend_time.txt
date +%s >> /tmp/suspend_time.txt
case "$1" in
suspend)
# executed on suspend
echo "%system_suspend" >> /tmp/suspend_time.txt
date +%s >> /tmp/suspend_time.txt
;;
resume)
# executed on resume
echo "%system_resume" >> /tmp/suspend_time.txt
date +%s >> /tmp/suspend_time.txt
;;
*)
;;
esac

You don't say what distribution you are running, but if you are running the systemd daemon, try putting it in /lib/systemd/system-sleep instead (note that the arguments are different).
Script:
[eje#irenaeus ~]$ sudo cat /lib/systemd/system-sleep/95test
[sudo] password for eje:
#!/bin/bash
echo $(date) "$#" >> /tmp/args
Output:
Sun Dec 20 02:45:51 PM EST 2020 pre suspend
Sun Dec 20 02:45:59 PM EST 2020 post suspend

Related

why does exec+tee output display out-of-order?

This is basically an addendum to this question:
redirect COPY of stdout to log file from within bash script itself
So using this test script:
#!/bin/bash
echo 'bash version:'
bash --version|grep release
echo '';
echo '----------------'
rm /tmp/logfile 2>/dev/null;
function testCommands() {
local mode="$1"
echo "testCommands(): mode == $mode";
# Link file descriptor #6 with stdout to save stdout, #7 for stderr
exec 6>&1;
exec 7>&2;
if [[ 'both' == "${mode}" ]]; then
# log to file and stdout
exec > >(tee -ia /tmp/logfile);
elif [[ 'file' == "${mode}" ]]; then
# log to file only
exec 1>> /tmp/logfile
elif [[ 'quiet' == "${mode}" ]]; then
# be quiet
exec 1> /dev/null
#else - use normal stdout
fi
if [[ 'true' != "${separate_stderr}" ]]; then
#by default, merge stderr to stdout for simple logging
exec 2>&1
#else - keep stderr separate like it normally is
fi
echo "fee";
echo "fye";
echo "foh";
echo "fum";
# Restore stdout/stderr and close file descriptors #6/#7
exec 1>&6 6>&-;
exec 2>&7 7>&-;
}
testCommands 'file'
echo '----------------'
echo ''
echo 'check /tmp/logfile'
ls -acl /tmp/logfile
echo ''
echo 'check output'
cat /tmp/logfile
rm /tmp/logfile 2>/dev/null;
echo '----------------'
testCommands 'stdout'
echo '----------------'
echo ''
echo 'check /tmp/logfile'
ls -acl /tmp/logfile
echo ''
echo 'check output'
cat /tmp/logfile
rm /tmp/logfile 2>/dev/null;
echo '----------------'
testCommands 'both'
echo '----------------'
echo ''
echo 'check /tmp/logfile'
ls -acl /tmp/logfile
echo ''
echo 'check output'
cat /tmp/logfile
rm /tmp/logfile 2>/dev/null;
echo '----------------'
testCommands 'quiet'
echo '----------------'
echo ''
echo 'check /tmp/logfile'
ls -acl /tmp/logfile
echo ''
echo 'check output'
cat /tmp/logfile
echo '----------------'
I get the following output:
bash version:
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
----------------
testCommands(): mode == file
----------------
check /tmp/logfile
-rw-rw---- 1 testuser testuser 16 Sep 20 16:10 /tmp/logfile
check output
fee
fye
foh
fum
----------------
testCommands(): mode == stdout
fee
fye
foh
fum
----------------
check /tmp/logfile
ls: cannot access '/tmp/logfile': No such file or directory
check output
cat: /tmp/logfile: No such file or directory
----------------
testCommands(): mode == both
----------------
check /tmp/logfile
fee
fye
foh
fum
-rw-rw---- 1 testuser testuser 16 Sep 20 16:10 /tmp/logfile
check output
fee
fye
foh
fum
----------------
testCommands(): mode == quiet
----------------
check /tmp/logfile
ls: cannot access '/tmp/logfile': No such file or directory
check output
cat: /tmp/logfile: No such file or directory
----------------
There is a fair bit of output here, so if you didn't see it the first time through, then part that looks weird is in the section testCommands(): mode == both.
What I would expect to see here is that all output from function would display first, then output from echo/ls/cat that is defined after the call. Instead function output displays between output from 2 commands that should be running after the function has completed. In other words, here is what I expect should happen (note: the below is not actual output - I made it up):
----------------
testCommands(): mode == both
fee
fye
foh
fum
----------------
check /tmp/logfile
-rw-rw---- 1 testuser testuser 16 Sep 20 16:10 /tmp/logfile
check output
fee
fye
foh
fum
I am running this from Linux Mint v19.2 x64 Cinnamon (based off Ubuntu 18.04) on my home computer. Was looking to adapt the exec answer from the other post to a shared functions.sh script that I plan to call from various other other bash shell scripts, my .bash_aliases, etc. I have some scenarios where I would like to call the same function in various scenarios which have different logging requirements: file + stdout, file only, stdout only, and silent. I prefer to stderr into stdout for all my scenarios.
1) Calling testCommands 'both', I see output from after the function displayed before output from the function itself. Curious if there is any way to confirm this is really due to buffering in tee, due to something else entirely, or some combination.
2) Is there any way to fix this from bash other than using the 'unbuffered version of tee' referenced in the other question? e.g. even if it is buffering, could I disable or even force printing buffered output before function ends via bash/other posix commands? I would prefer to avoid external dependencies but can't see myself switching to any distros that don't use bash as the default shell.
3) Is there a more elegant/flexible/easier-to-maintain way to go about controlling output when using bash? (e.g. managing the various permutations of display/hide the stdout/stderr output for console/logfile)
Here's an easier way to reproduce your issue:
echo "Hello" > >(tee -a file)
echo "World" >> file
The file will contain "World Hello" instead of "Hello World".
This does not happen because tee buffers (it doesn't), but because you have made writes a two stage process, and the shell only waits for the first one.
When you go via a process substitution, you are writing to a pipe, and echo will only wait until the data has been successfully written to the pipe. It won't make it into the file until tee gets a chance to write it later. If the script continues to cause writes to the file before tee can run, output appears out of order.
If you at any time want to "flush" the output, you'll have to close the pipe and wait for the process substitution to exit:
mkfifo tmpfile
exec > >(echo "$BASHPID" > tmpfile; exec tee -a file)
echo "Hello"
exec >&-
wait "$(<tmpfile)"
echo "World" >> file
So really it's easier to just ensure that all data takes the same path, e.g. by ensuring that all writes happen through the same process substitution.
Because command is buffering the IO. If you disable IO buffering you will get the results you want. You can the stdbuf or unbuffer command which will disable buffering.
stdbuf -oL command # This will buffer one line at time
unbuffer command
And if you system don't have one of these commands try script which is an older and should be on most distributions.
script -q /dev/null long_running_command

Shell script does not exit to the prompt

I have a shell script ws_appl_process that stop/start WebSphere servers:
#!/bin/sh
# ------------------------------------
# WebSphere Application Server process
# ------------------------------------
# PLEASE NOTE: This script assumes no spaces in the server names
# Finally, alter $APPSERVERS if server1 is required to start
PROF_HOME="/opt/WebSphere/AppServer855/profiles/xxxxxx"
## set colors
ec=`tput setaf 1` # error color
rc=`tput sgr 0` # reset color to default
if [ ! -d $PROF_HOME ];then
echo " "
echo "${ec}WARNING:${rc} unable to locate directory $PROF_HOME! No action taken."
echo " "
else
. $PROF_HOME/bin/setupCmdLine.sh
SERVERDIR=$PROF_HOME/config/cells/$WAS_CELL/nodes/$WAS_NODE/servers
APPSERVERS=`ls $SERVERDIR | egrep -v "jmsserver|nodeagent|web$"`
case "$1" in
'start')
# delay start by 30 seconds to let OS 'calm down' on startup
sleep 30
# start jmmserver first, if applicable
if [ -f $SERVERDIR/jmsserver/server.xml ]; then
$PROF_HOME/bin/startServer.sh jmsserver
fi
# start all servers found in config directory
for i in $APPSERVERS;do
$PROF_HOME/bin/startServer.sh $i &
sleep 1
done
;;
'stop')
for i in $APPSERVERS;do
$PROF_HOME/bin/stopServer.sh $i &
done
if [ -f $SERVERDIR/jmsserver/server.xml ]; then
$PROF_HOME/bin/stopServer.sh jmsserver
fi
;;
*)
echo "Usage: $0 { start | stop }"
exit 1
esac
fi
exit $?
Running this script
./ws_appl_process stop
will do what is intended, e.g. stop or start.
However, the script does NOT return to the prompt e.g. user#server:~>.
I have to manually hit the <RETURN> or <ENTER> key to get to the prompt.
I have tried to modify the last command
exit $?
to
exit 0
or
exit $?
exit 0
with no luck.
I need the script to return automatically to the prompt. The reason is that I am automating the monitor of the servers, and eventually bring them back, i.e.
./ws_appl_process start
The OS:
Linux xxxxxx 3.0.101-108.101-default #1 SMP Tue Aug 13 08:31:17 UTC 2019 (d0a7b7a) x86_64 x86_64 x86_64 GNU/Linux
The shell:
GNU bash, version 3.2.57(2)-release (x86_64-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
How can I force the script back to the prompt?
Appreciate any comments.

Error when using shutdown command in Bash

read -p 'Want to use the timer (y/n) ? ' jwb2
if [[ $jwb2 =~ ^[Yy]$ ]]; then
echo -n "Now Days "
date +"%A and hour %T"
read -p 'How many hours [24hrs] :' jwb3
echo Process the command
sudo bash -c "Shutdown -h $jwb3"
fi
and running the script now,
me#linux:$./main.sh
Want to use the timer (y/n) ? y
Now Days Thursday and hour 16:09:49
How many hours [24hrs] :18:00
Process the command
bash: Shutdown: command not found
Why am I getting this error?
Use shutdown instead Shutdown.

Bash script to re-launch program in case of failure error

In linux (I use a Ubuntu), I run a (ruby) program that continually runs all day long. My job is to monitor to see if the program fails and if so, re-launch the program. This consists up simply hitting 'Up' for last command and 'Enter'. Simple enough.
There has to be a way to write a bash script to monitor my program if its stops working and to re-launch it automatically.
How would I go about doing this?
A bonus is to be able to save the output of the program when it errors.
What you could do:
#!/bin/bash
LOGFILE="some_file.log"
LAUNCH="your_program"
while :
do
echo "New launch at `date`" >> "${LOGFILE}"
${LAUNCH} >> "${LOGFILE}" 2>&1 &
wait
done
Another way is to periodicaly check the PID:
#!/bin/bash
LOGFILE="some_file.log"
LAUNCH="your_program"
PID=""
CHECK=""
while :
do
if [ -n "${PID}" ]; then
CHECK=`ps -o pid:1= -p "${PID}"`
fi
# If PID does not exist anymore, launch again
if [ -z "${CHECK}" ]; then
echo "New launch at `date`" >> "${LOGFILE}"
# Launch command and keep track of the PID
${LAUNCH} >> "${LOGFILE}" 2>&1 &
PID=$!
fi
sleep 2
done
Infinite loop:
while true; do
your_program >> /path/to/error.log 2>&1
done

bash script not running as expected from cron vs. shell.

I have a script I got from this website and modified to suit my needs. Orginal post: Linux Script to check if process is running & act on the result
When running the script from cron, it always creates a new process. If I run it from shell it runs normally. Can anyone help me debug the issue ?
Script
[root#server2 ~]# cat /root/full-migrate.sh
#!/bin/bash
case "$(pidof perl | wc -w)" in
0) echo "Restarting iu-maildirtoimap: $(date)" >> /var/log/iu-maildirtoimap.txt
/usr/local/bin/iu-maildirtoimap -i currentuser.txt -D imap.gmail.com:993 -d -n7 -I&
;;
1) echo "Everything seems okay: $(date)" >> /var/log/iu-maildirtoimap.txt
;;
*) echo "Removed double iu-maildirtoimap: $(date)" >> /var/log/iu-maildirtoimap.txt
kill -9 $(pidof perl | awk '{print $1}')
;;
esac
crontab job
[root#server2 ~]# crontab -l
*/1 * * * * /bin/bash /root/full-migrate.sh
From the logfile:
Removed double iu-maildirtoimap: Tue Dec 30 02:32:37 GMT 2014
Removed double iu-maildirtoimap: Tue Dec 30 02:32:38 GMT 2014
Removed double iu-maildirtoimap: Tue Dec 30 02:32:39 GMT 2014
Everything seems okay: Tue Dec 30 02:32:39 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:33:01 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:34:01 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:35:01 GMT 2014
The first 4 entries are me manually running "/bin/bash /root/full-migrate.sh"
The last 3 are from the crontab.
Any suggestions on how to debug this issue ?
At the time of writing:
[root#server2 ~]# $(pidof perl | wc -w)
bash: 13: command not found
[root#server2 ~]# $(pidof perl | awk '{print $1}')
bash: 26370: command not found
Your test from the command line is not valid, because you are basically executing the process id, which will give you a command not found.
From the command line you will need to test this way:
$ pidof perl | wc -l
without the $()
The issue you are most likely having is that cron cannot find pidof in the path. So you will need to figure out where pidof resides on your system:
$ which pidof
and then put that full path in your cron job and it should work.

Resources