I need to execute a command or a script and wait for the end of executing (ash)

Have you tried putting into a detached shell?
with ( )&

( /bin/mykika/mykikaconsole.sh 10 )&

Then it should not care about the init script itself ending.

1 Like

doesnt work as well
i #sleep 12 in mykika and it is the same the mykikacomsole.sh started and stuck

I leave your problem

it is beyond my possibilities to give you a hand

the only advice I can give is to simplify the code

I guess your problem ist:

  • The ssh call connects both, stdin and stdout of the ssh terminal to your script.
  • Even though you force your script to the background, it still is connected to both of those streams.
  • Terminating the ssh connection means closing those streams.
  • So as soon as your script tries to "echo" something after ssh is closed, the script terminates because there's no output stream to echo to.

Example 1:

#!/bin/sh

start() {
        while :
        do
                sleep 1
        done
}

echo "setting up"
sleep 1
echo .
sleep 1
echo "set up"
start &

Call this script via ssh router ./fooo
Then ssh to the router and ps | grep fooo.

Result: There's a process runnng displayed as {fooo} /bin/sh ./fooo.

Kill that process to not mess up the next example.

Example 2

Now we add an "echo" to the background function.

#!/bin/sh

start() {
        while :
        do
                echo "fooo"
                sleep 1
        done
}

echo "setting up"
sleep 1
echo .
sleep 1
echo "set up"
start &

Call this script via ssh router ./fooo
Then ssh to the router and ps | grep fooo.

Result: This time there is no fooo process in place. The script died because it could not echo.

Example 3

Now we wrap the background process into a sub shell and forward its stdout and stderr to /dev/null

#!/bin/sh

start() {
        while :
        do
                echo "fooo"
                sleep 1
        done
}

echo "setting up"
sleep 1
echo .
sleep 1
echo "set up"
(start >/dev/null 2>&1 )&

And again: Call via ssh router ./fooo
Then ssh to the router and ps | grep fooo.
The script keeps running.

Conclusion

  • You totally run parts of your script blocking while parts of it are non blocking (that's what I did with the "set up" thing vs the "start" function.
  • You need to make sure your script doesn't perform any output (stdout as well as stderr) once the background non blocking secton starts.
  • You totally can use stdout as long as you keep your ssh connection open, which is the case as long as your script is blocking.

Call to action:

  • Rework the "logging" part of your script. Don't just "echo" it to stdout but put it to a proper logfile.
  • Rework your script by splitting it into a setup phase and a service phase.
  • Put the service phase to the background.
  • Keep your setup phase in foreground.
5 Likes

Up to this point this thread was doing nothing but going off at tangents.

Reading what you are now saying I have concluded you want:

  1. to start "MY KIKA" as a service daemon
  2. Make sure the wifi interfaces are all up before starting

If my conclusions are correct, you need to do two things.

  1. Add a "wait_for_interface" function to mykika's startup.
  2. Use OpenWrt's procd to start the service (not the legacy init.d)

The openNDS package has a similar requirement to ensure interfaces are up, so here is the wait_for_interface function extracted from there:

wait_for_interface () {
	local ifname="$1"
	local timeout=10

	for i in $(seq $timeout); do
		if [ $(ip link show $ifname 2> /dev/null | grep -c -w "state UP") -eq 1 ]; then
			ifstatus="up"
			break
		fi
		sleep 1
		if [ $i == $timeout ] ; then
			syslogmessage="$ifname is not up - giving up for now."
			debugtype="warn"
			write_to_syslog
			ifstatus="down"
		fi
	done
}

and its associated syslog call to replace all your echos to stdio


# Write debug message to syslog
# $syslogmessage contains the string to log
# $debugtype contains the debug level string: debug, info, warn, notice, err, emerg.
write_to_syslog() {

	if [ ! -z "$syslogmessage" ]; then
		#get_debuglevel # write some code to get debuglevel from your config
                # or set the debuglevel here
                debuglevel=3

		case $debugtype in
			"emerg") debugnum=0;;
			"err") debugnum=0;;
			"notice") debugnum=1;;
			"warn") debugnum=1;;
			"info") debugnum=2;;
			"debug") debugnum=3;;
			*) debugnum=1; debugtype="notice";;
		esac

		if [ "$debuglevel" -ge "$debugnum" ]; then
			echo -n "mykika - [$syslogmessage]" | logger -p "daemon.$debugtype" -t "opennds[$ndspid]"
		fi
	fi
}

Add the code for both these functions in place of your initial delaystart section at the beginning of the script file.

Now, get the wireless interface names you predefined in the wireless config and call wait_for_interface for each one.
eg:

ifname=wlan0
wait_for_interface

You could use a for loop to work through a list of ifnames if you like.
The result of this is that mykika will now wait for the wireless interfaces to be up (or you could exit if an interface times out).

The final step is to make your inid.d script procd compatible:

#!/bin/sh /etc/rc.common

START=90
STOP=01
USE_PROCD=1

start_service() {
	procd_open_instance
	procd_set_param command /bin/sh "/bin/mykika/mykikaconsole.sh"
	procd_close_instance
}

stop_service() {
	#add any post service stop cleanups here
}

Procd automatically runs service daemons in the background and keeps tabs on them, respawning as required.
Procd automatically keeps track of pid so knows what to do.

Use the write_to_syslog function whenever you want to report something.

You might also consider changing your config file to uci format and putting it in /etc/config

1 Like

so procd is better than runing in backgroud ?
i am gonna read for now about procd in OpenWrt
but the idea to make it like a service was in my head for some time ,thanks for tip
i am gonna try and then replay

i did like this dont work

#!/bin/sh /etc/rc.common
# Example script
# Copyright (C) 2007 OpenWrt.org

START=99
STOP=1
USE_PROCD=1

start_service() {
sleep 10
	procd_open_instance
	procd_set_param command /bin/sh " /bin/mykika/mykikaconsole.sh 10"
	procd_close_instance
}

stop_service() {
	#add any post service stop cleanups here
	kill -9 $(ps | grep 'mykika' | grep ash | awk '{print $1;}')
}

root@AP3:~# /etc/init.d/mykika stop
sh: you need to specify whom to kill
Command failed: Not found
root@AP3:~#

root@AP3:~# /etc/init.d/mykika stop_service
Syntax: /etc/init.d/mykika [command]

Available commands:
start Start the service
stop Stop the service
restart Restart the service
reload Reload configuration files (or restart if service does not implement reload)
enable Enable service autostart
disable Disable service autostart
enabled Check if service is started on boot
running Check if service is running
status Service status
trace Start with syscall trace
info Dump procd service info

At this point, procd has already killed your service daemon, so its pid does not exist.
You do not need to kill here. You probably do not need to do anything here. It is reserved for commands for post "service kill" processes you might need to do.

Procd does run the service daemon in the background. You don't have to tell it to do so.

But you need to add the wait_for_interface to your mykika script's startup and remove the "10" argument from the end of the procd_set_param as it will be ignored. Any command line arguments are handled by procd differently.

If you want to pass the 10 second sleep to mykika, add after procd_set_param line:
procd_append_param command 10

Note: You can still use the init.d syntax but it is deprecated, instead use the service command.
For example:
service mykika stop

The "available commands" are a list of Procd commands, not a list of functions in your init.d script.

The most commonly used are
service mykika start

service mykika stop

service mykika restart

and if you want to disable startup on boot:
service mykika disable

and to re-enable it on boot:
service mykika enable

what suould i use in stop service function

kill -9 $(ps | grep 'mykika' | grep ash | awk '{print $1;}')

is ok ?
i am tring now all this start restart

Leave it BLANK. This is for post "stop" cleanups like deleting unwanted log files or similar.

$(ps | grep 'mykika' | grep ash | awk '{print $1;}') will return an empty string because procd has already killed the service daemon.

1 Like

i removed stop_service function and all works good now i need to read about benefits procd
can it restart service if it freezz?

Procd is OpenWrt's version of systemd found in other Linux distros. It does pretty much all that systemd does but is much smaller and better suited to the OpenWrt environment.

If it crashes, procd will respawn it. If it freezes up but is still apparently running eg has gone into a tight loop, then you will have to do service mykika restart

For example if your code exits with exit code 1 ( exit 1 ) because the interfaces timed out, procd will interpret this as a crash and respawn. This can be very useful for automatic restarts.

So if i put im mykikaconsole.sh cheking if wlans are up and do exit 1 if not then procd will rewspawn the process ?
so maybe no need for delay at start ? but it takes about 10 seconds so it will be restarting process how many times ?
oh wait i can do like
if wlans not up
sleep 3
exit 1
oh wait your code do even beter cheacks every 1 sec

Yes. That is what wait_for_interfaces function that I posted allows you to do.

No need for a delay at the start. That is what wait_for_interfaces function does, it WAITS FOR INTERFACES

You would do for example:

wait_for_interface wlan0

if [ "$ifstatus" = "down" ]; then
        exit 1
fi
1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.