Bash calls two bash scripts - linux

I have the following script:
#!/bin/bash
if [ "$EUID" -ne 0 ]
then
echo ''
echo 'Please run the script as root'
echo ''
exit
fi
for run in {1..11}
do
sudo ./start_ap.sh
sleep 10
sudo ./tst.sh
done
The problem is that after executing
sudo ./start_ap.sh
the next lines will not be executed, because the line sudo ./start_ap.sh needs CTRL+C to stop and only then next lines will be executed.
However, I want that the sudo ./start_ap.sh will be terminated after sudo ./tst.sh and at next step this will be repeated 11 times.
So far, after execution of sudo ./start_ap.sh, the next lines will not be executed without killing its process.
How can I realize it?
P.S. start_ap.sh starts the hostapd and that's why it needs killing for next executions.

You need to run ./start_ap.sh in the background, then kill it after ./tst.sh completes. Note that if you actually run the script as root, there is no need to use sudo inside the script.
for run in {1..11}; do
./start_ap.sh & pid=$!
sleep 10
./tst.sh
kill "$pid"
done

Related

Bash run a group of two children in the background and kill them later

Let's group two commands (cd and bash ..) together like this:
#!/bin/bash
C="directory"
SH="bash process.sh"
(cd ${C}; ${SH})&
PID=$!
sleep 1
KILL=`kill ${PID}`
process.sh prints out the date (each second and five times):
C=0
while true
do
date
sleep 1
if [ ${C} -eq 4 ]; then
break
fi
C=$((C+1))
done
Now I actually would expect the background subprocess to be killed right after 1 second, but it just continues like nothing happens. INB4: "Why don't you just bash directory/process.sh" No, this cd is just an example.
What am I doing wrong?
Use exec when you want a process to replace itself in-place, rather than creating a new subprocess with its own PID.
That is to say, this code can create two subprocesses, storing the PID of the first one in $! but then using the second one to execute process.sh:
# store the subshell that runs cd in $!; not necessarily the shell that runs process.sh
# ...as the shell that runs cd is allowed to fork off a child and run process.sh there.
(cd "$dir" && bash process.sh) & pid=$!
...whereas this code creates only one subprocess, because it uses exec to make the first process replace itself with the second:
# explicitly replace the shell that runs cd with the one that runs process.sh
# so $! is guaranteed to have the right thing
(cd "$dir" && exec bash process.sh) &
you can check all child processes with "ps --ppid $$"
so,
#!/bin/bash
C="directory"
SH="bash process.sh"
(cd ${C}; ${SH})&
PID=$!
sleep 1
ps -o pid= --ppid $$|xargs kill

Propagate exit code from runuser command

I want to run the bash script, StartSomething.sh, as a specific user. I use runuser command for that. Also I want to know an exit code from this bash script. So I write an exit code to the file when the command is finished or interrupted. Here is the code:
runuser myuser -s /bin/bash -c "./StartSomething.sh --pidfile=${pidfile}; \
echo $? > ${statusfile};" &
sleep 5
pid=$(cat ${pidfile})
while ps -p ${pid} > /dev/null; do sleep 1; done
end=$(cat ${statusfile})
echo "End code: ${end}"
exit ${end}
Problem is that exit code is still 0, though bash script is interrupted. What can be wrong?
If I have separate file, start.sh, with this code:
./StartSomething.sh --pidfile=${pidfile}
echo $? > ${statusfile}
and runuser command look like this:
runuser myuser -s /bin/bash -c "./start.sh" &
everything is working fine. I want to use first example without separate file. Can someone tell me what can be wrong? Is there better solution for this problem?
If all you want to do is to run the program in the background, and wait for it to finish, I think you could also use wait to get the return value (runuser passes it through, unless something exceptional happens):
runuser myuser ./StartSomething.sh --pidfile=${pidfile} &
pid=$!
# do something else
wait $!
echo "it returned $?"
or
runuser myuser ./StartSomething.sh --pidfile=${pidfile} &
pid=$!
echo -n "waiting"
while kill -0 $pid 2>/dev/null; do
echo -n "."
sleep 1
done
echo
wait $!
echo "it returned $?"
There is problem with escaping special character $. Correct command:
runuser myuser -s /bin/bash -c "./StartSomething.sh --pidfile=${pidfile}; \
echo \$? > ${statusfile};" &
Replace $? with \$?.

script to check script is running and start it, if it’s stopped

I have a script with this name : Run.sh
I run this script with this command :
./run.sh
I don't like stop this script but this script Suddenly stops and need run again.
I need a script to check it , if my run.sh stopped , run it again.
this is run.sh codes:
#!/usr/bin/env bash
install() {
sudo apt-get update
sudo apt-get upgrade
}
if [ "$1" = "install" ]; then
install
else
if [ ! -f ./tg/tgcli ]; then
echo "tg not found"
echo "Run $0 install"
exit 1
fi
#sudo service redis-server restart
#./tg/tgcli -s ./bot/bot.lua -l 1 -E $#
./tg/tgcli -s ./bot/bot.lua $#
fi
And i want run this script at boot (with screen or tmux) if my server restart
i have Ubuntu 16.04 version
Thank you Ljm Dullaart
Can you help me about this ?
You should not need to run the complete bash script again. Changing
./tg/tgcli -s ./bot/bot.lua $#
to
while :; do
./tg/tgcli -s ./bot/bot.lua $#
done
will restart bot.lua everytime it exits.
You can check if your run.sh is running and re-run it if stopped with a single command:
$ if ! pgrep run.sh ;then /path/to/run.sh;fi
If script runs pgrep will return exit status 0 = success and will print the pid of run.sh
If script does not run pgrep will return exit status 1 and then script will be called.
You can also use pgrep inst.sh >/dev/null to "mute" pgrep in case script is running.

Bash script iterate over PID's and kill items

I try to kill all occurrences of a process, what's happen actually an iteration stops after first item, what's wrong here ?
#!/usr/bin/env bash
SUPERVISORCLS=($(pidof supervisorctl))
for i in "${SUPERVISORCLS[#]}"
do
echo $i
exec sudo kill -9 ${i}
done
Before I tried sth like this as solution for restart script, but as well script was not always executed at total always only one if block was executed.?
ERROR0=$(sudo supervisord -c /etc/supervisor/supervisord.conf 2>&1)
if [ "$ERROR0" ];then
exec sudo pkill supervisord
exec sudo supervisord -c /etc/supervisor/supervisord.conf
echo restarted supervisord
fi
ERROR1=$(sudo supervisord -c /etc/supervisor/supervisord.conf 2>&1)
if [ "$ERROR1" ];then
exec sudo pkill -9 supervisorctl
exec sudo supervisorctl -c /etc/supervisor/supervisord.conf
echo restarted supervisorctl
fi
exec replaces your process with the executable that's the argument to it, so you will never execute another statement in your script after it hits an exec. Your process will no longer exist. In the first example your process will no longer be your script it will be kill and pkill in the second.
To fix it, just remove exec from all those lines. It's not needed. When executing a script the shell will execute the commands on every line already, you don't have to tell it to do so.

send control c to a linux command after specific time intervel?

Shell Scripting:
I am doing some testing on my router, I am using mdk3 and reaver utility for that.
here are the two commands:
[cmd1] echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv -l 230
[cmd2] sudo mdk3 wlan2mon a -a 00:FF:EE:CC:DS:B6
goal:
I am trying to create a shell script which will run [cmd1] for 2 minutes, then it will send the ctrl + c signal to [cmd1] so that it will save the reaver session.
then cmd2 will run for 2 minutes and this will also stop after that.
these two will be in loop.
below is the sample script which I written can you add timer to it..?
#!/bin/bash
while :; do echo
echo "running mdk for 2 minutes";
timeout 120 sudo mdk3 wlan2mon a -a 00:FF:EE:CC:DS:B6;
echo "mdk finished";
echo "starting reaver for 2 minutes ";
#here timeout won't work, as ctrl+c can only save the state.
//add code here to run reaver utility for two minutes and send ctrl+c to it
echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv;
echo "reaver ran for two minutes";
done
I'm not familiar with the reaver program, but I think the following should work,
# Run reaver as a background process (add &)
echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv &
# Save the process id.
reaverpid=$!
# Sleep 2 minutes
sleep 120
# Send SIGINT, which is what ctrl-c normally does.
kill -SIGINT $reaverpid

Resources