The above answers are the standard/"right" way to do it.
Another approach that's simpler from a more "end user" point of view is to have any scheduled or background task write its output to a "log" file. The file can be anywhere on your system, but if the task is running as root (from cron
, etc.), then somewhere under /var/log
is a good place to put it.
I created the /var/log/maint
directory and made it readable by everybody and I have a readable file under that called "backup" where I log the output from my backup scripts.
I made my own directory so my files don't get mixed in with things generated by the system.
To put stuff there (in bash):
BACKUP="/var/log/maint/backup"
echo "my message" >> "${BACKUP}"
The >>
causes the messages to be appended to the file instead of overwriting it each time.
If my script has a lot of output, I use a script or function for output so everything gets done the same. Below is my current (overkill version): (the VERBOSE stuff is there for when I'm running the script from a terminal and want to see what's going on for debugging purposes.)
#!/bin/bash
## backup_logger
## backup system logging module
## Copyleft 01/20/2013 JPmicrosystems
## Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]
## If present, -v says log to console as well as to the log file
## <caller> is the name of the calling script
## If <caller> <log message text> is not present, write a blank line to the log
## Must be placed in path, like ~/bin
## If log is owned by root or another user, then this must run as root ...
## If not, it just aborts
##source "/home/bigbird/bin/bash_trace" ## debug
SCRIPT_NAME="$(basename $0)"
USAGE="Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]"
SYSLOGDIR='/var/log/maint'
SYSLOGFILE="${SYSLOGDIR}/backup.log"
LOGGING=1
VERBOSE=0
if [ "${1}" == "-v" ]
then
VERBOSE=1
shift
fi
##LOGGING=0 ## debug
##VERBOSE=1 ## debug
## Only zero or two parameters allowed - <caller> <log message text>
RC=0
if [ "$#" -eq 1 ] || [ "$#" -gt 2 ]
then
echo "${USAGE}"
RC=1
else
if [ ! -w "${SYSLOGFILE}" ]
then
touch "${SYSLOGFILE}"
if [ $? -ne 0 ]
then
echo -e "$(date) ${1} ${2}"
echo "${SCRIPT_NAME} Can't write to log file [${SYSLOGFILE}]"
RC=1
exit ${RC}
fi
fi
if [ -n "${1}" ]
then
(( LOGGING )) && echo -e "$(date) ${1} ${2}" >> "${SYSLOGFILE}"
(( VERBOSE )) && echo -e "$(date) ${1} ${2}"
else
(( LOGGING )) && echo "" >> "${SYSLOGFILE}"
(( VERBOSE )) && echo ""
fi
fi
exit $RC
Edit: Simplistic at
example which writes to a user file
Haven't used this in forever, so I figured it out with a couple of simple scripts.
The first script just schedules the event using at
. The command itself could just be typed into a terminal, but I'm lazy - especially when I have to do it multiple times while testing it without fooling with command history.
#!/bin/bash
## mytest_at_run
## Schedule a script to run in the immediate future
echo "/home/bigbird/bin/mytest_at_script" | at 00:56
The second script is the one which is scheduled to run
#!/bin/bash
## mytest_at_script
## The script to be run later
echo "$(date) - is when this ran" >> /home/bigbird/log/at.log
I created both scripts in a text editor, saved them, and then made them each executable using chmod 700 script-file-name
. I put them both in my $HOME/bin
directory for convenience, but they could be anywhere my user has full access. I use 700
for any script that's just for testing, but on a single user system, it could just as well be 755
.
I already have a directory called /home/bigbird/log
to save the output from mytest_at_script
. This can also be anywhere your user has full access. Just make sure it exists before the script runs or have the script create it.
To run it, I just made sure the time for the at
command in mytest_at_run
was a little bit in the future and then ran it from a terminal. I then waited until it ran and examined the contents of $HOME/log/at.log
.
bigbird@sananda:~/bin$ cat ~/log/at.log
Fri Sep 14 00:52:18 EDT 2018 - is when this ran
Fri Sep 14 00:56:00 EDT 2018 - is when this ran
bigbird@sananda:~/bin$
A few notes:
Even though I'm running at
from my user, it doesn't know my environment such as my PATH
and my home directory, so I don't assume that. I use full paths like I would for any cron
job. And if I ever want to make it a cron
job, I won't have to change anything just to make it run.
I used >>
in mytest_at_script
to append output to the log file instead of >
which would have replaced it on every run. Use whichever one suits your application best.
sleep 3m; echo Running
– Jasen Sep 14 '18 at 6:35