Daemon not executing shell file

Hey guys,

I'm rather new to scripting with the shell (I started on Wednesday) and encountered a problem that left me clueless.

I moved to an old house recently and the sound of the 433mhz door bell is too quiet. Since I always wanted to start playing around with a raspberry pi and my wife allowed me to get a new toy, I got one.
Now the pi receives the signal from the door bell's sender and activates several wireless sockets around the house, making it impossible to not notice that someone is at the door.

My first script was in php, but the infinity loop waiting for the signal took too much ressources and I wanted to optimize it - so I made some shell scripts.
I made the php script a daemon, because I restart the pi sometimes and didn't want to forget starting the 'bell expander'. That worked well.
Now I made my shell script a daemon and that works not so well. It starts, idles at low cpu load and waits for signals. It receives them, logs the time and such but does not execute the script that controls the wireless sockets. And I have no clue why.

Please have mercy with my script... :slight_smile:

First script, started as a daemon, listens for incoming signals, logs some stuff and triggers the second script (well, at least it should...)
/home/pi/tuerklingel_ueberwachung:

#!/bin/bash
TRIGGERED=0
NOW=`date +"%d.%m.%Y, %R:%S"`
RING=0

echo "$NOW Uhr          Starte �berwachung nach Reboot" >> /home/pi/tuerklingel.log

exec 3<>/dev/tcp/localhost/5000

printf '{"action":"identify","options":{"receiver":1},"uuid":"0000-00-00-70-161865"}'>&3

read -r RETURN <&3
if [ "${RETURN}" = '{"status":"success"}' ]
then
        echo "$NOW Uhr          Prozess erfolgreich gestartet" >> /home/pi/tuerklingel.log
else
        echo "$NOW Uhr          Prozess nicht gestartet, es ist ein Fehler aufgetreten" >> /home/pi/tuerklingel.log
        return 0
fi

while true
do
        read -u 3 -r RETURN
        unit=$(echo $RETURN | jq -r '.message.unit')
        id=$(echo $RETURN | jq -r '.message.id')
        systemcode=$(echo $RETURN | jq -r '.message.systemcode')
        unitcode=$(echo $RETURN | jq -r '.message.unitcode')
        NOW=`date +"%d.%m.%Y, %R:%S"`
        TIMESTAMP=`date +"%s"`
        TIMESTAMP=`expr $TIMESTAMP - 7`
        if [ "$TRIGGERED" -lt "$TIMESTAMP" ]
        then
                if [ "$systemcode" = "2" ] && [ "$unitcode" = "6" ]
                then
                        echo "$NOW Uhr          Klingel 1 wurde bet�tigt" >> /home/pi/tuerklingel.log
                        RING=1
                elif [ "$id" = "D7" ] && [ "$unit" = "23" ]
                then
                        echo "$NOW Uhr          Klingel am Tor wurde bet�tigt" >> /home/pi/tuerklingel.log
                        RING=1
                elif [ "$id" = "F10" ] && [ "$unit" = "32" ]
                then
                        echo "$NOW Uhr          Klingel am Haus wurde bet�tigt" >> /home/pi/tuerklingel.log
                        RING=1
                fi

                if [ "$RING" -eq 1 ]
                then
                        /bin/bash /home/pi/tuerklingel_meldung
                        TRIGGERED=`date +"%s"`
                        echo "$NOW Uhr          Gongs und Lichter ausgel�st" >> /home/pi/tuerklingel.log
                        RING=0
                fi
        fi

done

The second script calls all the different scripts that activate/deactivate the wireless sockets. I seperated each of the scripts so that I don't have to restart the daemon when I change something and to control the sockets individually, like how long they are active and so on. Some sleep for a few seconds because they activate flashing lights, for example.
/home/pi/tuerklingel_meldung

tuerklingelbefehle/blaulichtAn & tuerklingelbefehle/lidlGongAn & tuerklingelbefehle/ouboGongAn

And this is the init script:

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi
### BEGIN INIT INFO
# Provides:          Funkklingel-�berwachung
# Required-Start:    $remote_fs $syslog $network pilight
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Ausl�sen der Klingel �berwachen
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: Foo Bar <foobar@baz.org>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

DESC="Ausl�sen der Klingel �berwachen"
DAEMON=/home/pi/tuerklingel_ueberwachung
NAME=tuerklingel
#DAEMON_ARGS="--options args"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/tuerklingel_ueberwachung


do_start_cmd() {
        start-stop-daemon --background --start --quiet --pidfile ${PIDFILE} -m \
            --startas $DAEMON --name $NAME --test -c 1000 > /dev/null \
            || return 1
        start-stop-daemon --background --start --quiet --pidfile ${PIDFILE} -m \
            --startas $DAEMON --name $NAME -c 1000 \
            || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
        # on this one.  As a last resort, sleep for some time.
}

The weird thing is - it works like a charm when I execute the /home/pi/tuerklingel_ueberwachung manually. But if it runs as a daemon, it doesn't execute /home/pi/tuerklingel_meldung. And I have no idea why...

The daemon runs as the user pi, the user that owns all the scripts. chmod a+x is set for every script.
It doesn't matter how I try to call /home/pi/tuerklingel_meldung, it doesn't work.
I tried

  • . /home/pi/tuerklingel_meldung
  • /home/pi/tuerklingel_meldung
  • /bin/bash /home/pi/tuerklingel_meldung
  • sh /home/pi/tuerklingel_meldung

and possibly some other variations that I don't remember at the moment.

Please help me! :slight_smile:
Kind Regards
Matthias

OK, not all is clear for me yet, but lets try to understand what you did /do ... and what is failing...

OK but then

What is the difference between both ? because saying " if it runs as a daemon" doesnt tell how that is achieved... If its thru your init script ? If so did you try manually your execution using the init script AND after try using cron/at to launch only tuerklingel_ueberwachung and compare
You try, and give us the results I am tempted to say when you run a script that work ( interactive mode) and does not when called in batch mode, look carefully at your environment, you have something the batch mode is unaware that it need to properly execute what you want...

1 Like

The first suspect as a guess: environment variables. It could be as simple as the PATH variable not existing or wrong.

vbe is right though, there is not a lot of useful information to go on.

1 Like

Thank you for your answers and sorry for anything unclear. English is far from being my first language and scripting is really new for me.

I'll try to explain.

The init script starts "tuerklingel_ueberwachung" (door bell monitoring) as a daemon. It runs in the background and waits for incoming signals.
Everything seems ok, the logging works and I even get log entries for the last if-statement, it just doesn't execute the line "/bin/bash /home/pi/tuerklingel_meldung" (door bell report), no matter how I try to call it. The variables get set, the line gets logged, but the script tuerklingel_meldung does not get executet.
I added a line to tuerklingel_meldung to log if it gets called, but nothing happens. So the error must be in the daemonized script. Or the process of... uhm... daemonization...

If I start the script "tuerklingel_ueberwachung" manually from the shell, like ./tuerklingel_ueberwachung, it listens, logs and executes the script for reporting like I want it to, no problem at all, just one loud cacophony of wireless door bells all over the house.

I used relative and absolute paths, but neither did work.

I executed the init script manually, like vbe asked me to, and it worked, too. When started via cron the same faulty behaviour occurs.

We agree executing "tuerklingel_ueberwachung" via cron or using at, yes?

In which cse you must have something set in your environment missing for the batch mode to work most likely like Jim and I think, a variable, or $PATH settings

Try sourcing your environment ( add tests to remove interractive parts lik TTY business or it will complain... ) as first ( well second...) line of your "tuerklingel_ueberwachung" script and test again in batch mode

1 Like

Yes, I executed "tuerklingel_ueberwachung" via cron and had the same behaviour like running it as daemon.

I don't understand "sourcing your environment"? Like env/printenv?

Calling env from the manually started tuerklingel_ueberwachung returns

XDG_SESSION_ID=c4
SHELL=/bin/bash
TERM=xterm
HISTSIZE=999
SSH_CLIENT=192.168.178.28 4611 22
SSH_TTY=/dev/pts/0
USER=pi
HISTFILESIZE=0
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
MAIL=/var/mail/pi
_=/usr/bin/env
PWD=/home/pi
EDITOR=vim
LANG=de_DE.UTF-8
HISTCONTROL=ignoreboth
HOME=/home/pi
SHLVL=2
LS_OPTIONS=--color=auto -h -al --group-directories-first
LOGNAME=pi
SSH_CONNECTION=192.168.178.28 4611 192.168.178.24 22
XDG_RUNTIME_DIR=/run/user/1000

while calling env from the daemon returns significantly less lines:

PATH=/sbin:/usr/sbin:/bin:/usr/bin
PWD=/
LANG=de_DE.UTF-8
SHLVL=1
HOME=/home/pi
_SYSTEMCTL_SKIP_REDIRECT=true
_=/usr/bin/env

soooo... There's a difference and that should be the problem, shouldn't it? I'm pretty sure I don't need this ls_colors thing, but PATH has to be adjusted - just like you guys guessed :slight_smile: - and maybe other vars too?

Staring at above tuerklingel_ueberwachung again and again for a long time, some questions come up:

  • is date executed correctly, so NOW=`date +"%d.%m.%Y, %R:%S"` and TIMESTAMP=`date +"%s"` are being set? If, say, TIMESTAMP is empty or unset, none of the if branches will be entered even if TRIGGERED is initialized to 0 , as 0 won't be -lt ""
  • what is jq doing? Is it correctly executed without a valid PATH? If not, the main if branch might be entered but none of the "sub- if s", RING will remain 0 , and tuerklingel_meldung again wouldn't be executed.

Put in some echo / printf statements to log the contents of above variables to a file. You might want to execute with the -x option to bash set.

Is it on purpose that you mix the (deprecated) `...` and $(...) versions of "command substitution"?

1 Like

No, it's not. :slight_smile: I used what came into my mind first. But I will fix that. Is there anything else I should make better?

date is correctly executed, yes. The logs contain the correct date/time for every line and the if branches are triggered, the corresponding log lines are present.

jq works as well, I logged the variables and they are all set. $RETURN contains json and I need the unit-/systemcodes from different senders to identify which one was used. That works, too. The log contains every line it should contain.

Did you print all the variables JUST before the tests are done?

1 Like

Sorry, I don't understand. Do you mean print the variables in the line directly preceeding the if-condition?

---------- Post updated at 03:42 PM ---------- Previous update was at 03:34 PM ----------

Well, it was the working directory.
Adding "cd /home/pi" solved it. But I was using absolute paths, could anybody explain what was wrong with that?

And thank you guys! That was really kind, I appreciate your help. Hope I can give sth in return some day. :slight_smile:

Sourcing means executing with dot . your env file you use in your profile, can be .profile, .kshrc .bashrc etc...
Let's say you just modified your environment like you just added an alias:
alias='ls -la' #this is for most sh and ksh, the syntax may differ for her and is for csh...
Now you want to test lets say you modified .kshrc, to test there is no need to log out and connect again, you can also:

 . ./.kshrc 

Now you can also add the above to be executed at the beginning of your script, the only problem is your environment is done to meet interactive mode e.g standard input/output etc... are set, which is of no use and more gererates error when being set as for instance you dont have a display...
So either you accept all the errors hoping it will continue anyway ( because you are testing - you want to see there is something there missing for batchmode... ) you see it works so you are then left to find out what... Either you test if batchmode or interactive and use an if to skip what is set for interactive in your .profile

I was also puzzled by your if test as it looked as you were comparing a char with a char or numeric ( -lt ) "$value" is to me a char ( or could be seen as a string of one or more characters... ) so it cant be less than as less than means you are dealing with numbers
To be sure I have a num in a variable affection I use e.g.

 let RING=0 

So here

 if [ "$RING" -eq 1 ] 

I really have a doubt but I am not a bash user and so maybe that can pass...
Only here is where things get tricky, on a true UNIX system init uses /bin/sh and its path is very.very limited: /bin:/usr/bin... And you dont know where you are: if it needs to write in current directory. depending where, you find yourself ( as user is pi..) with no permissions....
And I am not sure that a real Bourne shell would like the above if test... and so it will never execute what you expected
All that to say it may work for you but it may very well in that case, be portable, so complying to old standards have an advantage, old guys like some of us will very easily point out the errors or issues, using fancy last versions of shells that we may not use makes things far more difficult to read, understand and test...

All the best and welcome here