Struggling to write a non-killable process

  • ATTENTION! As of November 1, 2020, you are not able to reply to threads 6 months after the thread is opened if there are more than 500 posts in the thread.
    Threads will not be locked, so posts may still be edited by their authors.
    Just start a new thread on the topic to post if you get an error message when trying to reply to a thread.

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?
 

ColinTaylor

Part of the Furniture
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.
 

Jack Yaz

Part of the Furniture
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!
 

ColinTaylor

Part of the Furniture
Updated my post to add:

-- Well there is, sort of. Don't invoke the commands/scripts from a terminal session. Invoke them from a cron job instead.
 

Jack Yaz

Part of the Furniture
Updated my post to add:

-- Well there is, sort of. Don't invoke the commands/scripts from a terminal session. Invoke them from a cron job instead.
Would launching via services-start or whatever work in a similar fashion?
 

ColinTaylor

Part of the Furniture
Would launching via services-start or whatever work in a similar fashion?
I would imagine so. I think it's only really a problem with busybox's interactive shell.

Putting the following line in a shell script seems to keep it running after logging off (assuming nohup and &).
Code:
trap '' SIGHUP
 
Last edited:

Jack Yaz

Part of the Furniture
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
 

SomeWhereOverTheRainBow

Very Senior Member
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:
 

Dabombber

Senior Member
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
 

Jack Yaz

Part of the Furniture
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? ;-)
 

Dabombber

Senior Member
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
 

Jack Yaz

Part of the Furniture
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.
 

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