My setup shares ingredients with many similar queries, but seems to have a unique problem to. it.
I have a lengthy PHP process running at the command line with output to stdout. It is lengthy enough I would like to run it in the background while monitoring its output in real time via a log file, so I direct its output to a file (>> log.out) and detach it from terminal and run in the background with nohup. Finally, I want to make sure the process restarts if it crashes or my server reboots, so I have a cron job that periodically executes a shell script that checks if the process is already running, and if not, launches it. Here is the relevant part of the bash script:
now=$(date)
echo "restarting daemon at $now"
nohup php /home/me/code/daemon.php >> /home/me/logs/daemon.log &
If execute the script myself from the command line, it works beautifully: it starts the process in the background, and the process logs its out continuously to the daemon.log where I can inspect it. Here’s the command line I use (*):
/bin/bash /home/me/code/tickle_daemon.sh >> /home/me/logs/tickle_daemon.out 2>&1
However, if I execute exactly the same command from cron, then the php process' output is buffered and does not appear in daemon.log until the process quits or is killed (at which point all of the output generated by the process appears at once). Note in both cases the actual process is running facelessly in the background; the difference is only whether the shell script launching that process into the background is itself running from an interactive command line or from a shell script.
So my question: what is different between cron and command-line execution of the shell script, and how can I force this chain of events to keep my innermost process's output unbuffered?
In terms of what I’ve tried, following suggestions here, I’ve experimented with using stdbuf to turn off buffering by prefixing "stdbuf -o0 -e0" to a variety of things, including
- the php invocation inside my nohup command
- the nohup invocation inside my shell script
- the shell script invocation inside my cron tab
But none of these eliminate the buffering I’m seeing.
I’ve also explored php’s own buffer-flushing commands (e.g. flush()), but these also have no effect. My own interpretation of docs is these should be irrelevant; output buffering is always off in command-line invocations (https://www.php.net/manual/en/outcontrol.configuration.php).
Can anyone help?
Thanks, Nick
(* Yes, I know I'm logging the shell script output to one file as well as the daemon's output to another. This is so I can keep track of how often the daemon needs restarting. Buffering isn't an issue for this second log file, since the shell script completes instantaneously on each cron tickle; it's only the inner PHP process, which does not complete instantly, whose output is being stalled somewhere.)