What's new

Struggling to write a non-killable process

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Jack Yaz

Part of the Furniture
I'm working on a project that involves leaving a permanent tail running, e.g.:

Code:
tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 | /opt/share/dnsmasq.awk >> /opt/share/dns.log
I've tried nohup, & , combinations thereof, but the process is always killed whenever I exit the SSH session. What am I missing?
 
IIRC from my own experiments if you nohup / & a binary executable (like tail) it will keep running when you log out. The problem comes when you try to do the same with a script (like .sh or .awk). Because these are invoked from the busybox shell they are killed when the shell (terminal) session terminates. From what I remember of looking at the source code there wasn't an obvious was around this. -- Well there is, sort of. Don't invoke the commands/scripts from a terminal session. Invoke them from a cron job instead.
 
IIRC from my own experiments if you nohup / & a binary executable (like tail) it will keep running when you log out. The problem comes when you try to do the same with a script (like .sh or .awk). Because these are invoked from the busybox shell they are killed when the shell (terminal) session terminates. From what I remember of looking at the source code there wasn't an obvious was around this.
Maybe I'll just write a binary in Go or something that does what I need, in that case :)

Thanks!
 
I would imagine so. I think it's only really a problem with busybox's interactive shell.

Putting the following line in shell script seems to keep it running after logging off (assuming nohup and &).
Code:
trap '' SIGHUP
That worked! Since I need to be sure entware/USB is mounted, I've worked it into an init.d script to kick things off - a symlink to /opt/bin satisfies the "PROC":
Code:
#!/bin/sh

ln -s /opt/share/taildns /opt/bin 2>/dev/null
chmod 0755 /opt/bin/taildns

if [ "$1" = "stop" ]; then
        for pid in $(ps | grep "tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3" | grep -v grep | awk '{print $1}') ; do
                kill "$pid"
        done
fi

ENABLED=yes
PROCS=taildns
ARGS=""
PREARGS=""
PRECMD=""
POSTCMD=""
DESC=$PROCS
PATH=/opt/sbin:/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

. /opt/etc/init.d/rc.fun
The script is then just a one liner (well 2)
Code:
#!/bin/sh
tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 | /opt/share/dnsmasq.awk >> /opt/share/dns.log
 
That worked! Since I need to be sure entware/USB is mounted, I've worked it into an init.d script to kick things off - a symlink to /opt/bin satisfies the "PROC":
Code:
#!/bin/sh

ln -s /opt/share/taildns /opt/bin 2>/dev/null
chmod 0755 /opt/bin/taildns

if [ "$1" = "stop" ]; then
        for pid in $(ps | grep "tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3" | grep -v grep | awk '{print $1}') ; do
                kill "$pid"
        done
fi

ENABLED=yes
PROCS=taildns
ARGS=""
PREARGS=""
PRECMD=""
POSTCMD=""
DESC=$PROCS
PATH=/opt/sbin:/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

. /opt/etc/init.d/rc.fun
The script is then just a one liner (well 2)
Code:
#!/bin/sh
tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 | /opt/share/dnsmasq.awk >> /opt/share/dns.log
Beautifully brilliant.- Something Amazing Just Happen!:eek::eek::cool:
 
There's no need to follow the format of the other init scripts so closely. It could be as simple as

Code:
#!/bin/sh

case "$1" in
    start)
        tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 | /opt/share/dnsmasq.awk >> /opt/share/dns.log &
    ;;
    stop)
        for PID in "$(ps | awk '$5" "$6" "$7" "$8=="tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3"{print $1}')"; do
            kill "$PID"
        done
    ;;
esac
 
There's no need to follow the format of the other init scripts so closely. It could be as simple as

Code:
#!/bin/sh

case "$1" in
    start)
        tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 | /opt/share/dnsmasq.awk >> /opt/share/dns.log &
    ;;
    stop)
        for PID in "$(ps | awk '$5" "$6" "$7" "$8=="tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3"{print $1}')"; do
            kill "$PID"
        done
    ;;
esac
I'd rather use the standard format, because it includes checks for already running etc. if you issue multiple starts (for whatever reason). Your example would allow for simultaneous tails. Why reinvent the wheel? ;-)
 
I'd rather use the standard format, because it includes checks for already running etc. if you issue multiple starts (for whatever reason). Your example would allow for simultaneous tails. Why reinvent the wheel? ;-)
I wasn't sure if it was allowed to be run multiple times since you loop through and possibility kill multiple processes when stopping. The best way to limit it would be to store the pid of the tail process, which is kinda annoying since there's no job support included.

Code:
#!/bin/sh

case "$1" in
    start)
        if [ ! -f /tmp/.taildns.pid ] || ! kill -0 "$(cat /tmp/.taildns.pid)" 2>/dev/null; then
            [ -p /tmp/.taildns.fifo ] || mknod /tmp/.taildns.fifo p
            tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 > /tmp/.taildns.fifo &
            PID=$!
            /opt/share/dnsmasq.awk < /tmp/.taildns.fifo >> /opt/share/dns.log &
            printf '%s\n' "$PID" > /tmp/.taildns.pid
        fi
    ;;
    stop)
        if [ -f /tmp/.taildns.pid ]; then
            kill "$(cat /tmp/.taildns.pid)" 2>/dev/null
            rm -f /tmp/.taildns.fifo /tmp/.taildns.pid
        fi
    ;;
esac
 
I wasn't sure if it was allowed to be run multiple times since you loop through and possibility kill multiple processes when stopping. The best way to limit it would be to store the pid of the tail process, which is kinda annoying since there's no job support included.

Code:
#!/bin/sh

case "$1" in
    start)
        if [ ! -f /tmp/.taildns.pid ] || ! kill -0 "$(cat /tmp/.taildns.pid)" 2>/dev/null; then
            [ -p /tmp/.taildns.fifo ] || mknod /tmp/.taildns.fifo p
            tail -F /opt/var/log/dnsmasq.log /opt/var/log/dnsmasq.log3 > /tmp/.taildns.fifo &
            PID=$!
            /opt/share/dnsmasq.awk < /tmp/.taildns.fifo >> /opt/share/dns.log &
            printf '%s\n' "$PID" > /tmp/.taildns.pid
        fi
    ;;
    stop)
        if [ -f /tmp/.taildns.pid ]; then
            kill "$(cat /tmp/.taildns.pid)" 2>/dev/null
            rm -f /tmp/.taildns.fifo /tmp/.taildns.pid
        fi
    ;;
esac
Again, the standard template does this just fine. You're adding unnecessary complexity.
 
I just using these command to keep it run:
ssh admin@192.168.1.1 "/jffs/my_custom_script.sh &"

Without nohup, the ssh return immediately and the program running.
Using this command to get details :
ssh admin@192.168.1.1 "ps"

============
Used on Merlin 386.2_4
 
Last edited:

Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top