Udev : detach script to wait for mounting - sleep

I made a simple udev rule which launch effectively my script :
KERNEL=="sdc", ACTION=="add", SUBSYSTEMS=="usb", ATTRS{manufacturer}=="Bookeen", ATTRS{product}=="Cybook", RUN+="/home/nap/Scripts/Wallabag.sh"
The udev rule is properly working, and launch the following script :
#!/bin/bash
sleep 5
(
exec </dev/null >/home/nap/usb.log 2>&1
set -x
mkdir /media/nap/Cybook/Test
) &
It's supposed to detach and let time to drive to auto-mount, but the mount is still made after the exit of the script.
I've already tried with " & disown" with same effect.
I've also tried to run my script inside another one, as decribed here, with same effect.
Am I doing something wrong ?
Thank you for your answers.

The processes started by udev's RUN= directive should be short-running. I would like to suggest a simpler way of decoupling long-running process from udev by using system scheduler at command:
KERNEL=="sdc", ACTION=="add", ATTRS{product}=="Cybook", RUN+="/usr/bin/at -M -f /home/nap/Scripts/Wallabag.sh now"
Just make sure that your /home/nap/Scripts/Wallabag.sh script is /bin/sh compatible - this is the shell that at uses. It should be more than enough to implement either simple sleep delay or polling for /media/nap/Cybook availability/readiness.

Related

How to run Bash Script on startup and keep monitoring the results on the terminal

Due to some issues I wont elaborate here to not waste time, I made a bash script which will ping google every 10 minutes and if there is a response it will keep the loop running and if not then the PC will restart. After a lot of hurdle I have been able to make the script and also make it start on bootup. However the issue is that i want to see the results on the terminal, meaning I want to keep monitoring it but the terminal does not open on bootup. But it does open if I run it as ./net.sh.
The script is running on startup, that much I know because I use another script to open an application and it works flawlessly.
My system information
NAME="Linux Mint"
VERSION="18.3 (Sylvia)"
ID=linuxmint
ID_LIKE=ubuntu
PRETTY_NAME="Linux Mint 18.3"
VERSION_ID="18.3"
HOME_URL="http://www.linuxmint.com/"
SUPPORT_URL="http://forums.linuxmint.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/linuxmint/"
VERSION_CODENAME=sylvia
UBUNTU_CODENAME=xenial
The contents of my net.sh bash script are
#! /bin/bash
xfce4-terminal &
sleep 30
while true
do
ping -c1 google.com
if [ $? == 0 ]; then
echo "Ping Sucessful. The Device will Continue Operating"
sleep 600
else
systemctl reboot
fi
done
I have put the scripts in /usr/bin and inserted the scripts for startup at boot in /etc/rc.local
So I did some further research and with help from reddit I realized that the reason I couldnt get it to show on terminal was because the script was starting on bootup but I needed it to start after user login. So I added the script on startup application (which can be found searching on start menu if thats whats it called). But it was still giving issues so I divided the script in two parts.
I put the net.sh script on startup and directed that script to open my main script which i named net_loop.sh
This is how the net.sh script looks
#! /bin/bash
sleep 20
xfce4-terminal -e usr/bin/net_loop.sh
And the net_loop.sh
#! /bin/bash
while true
do
ping -c1 google.com
if [ $? == 0 ]; then
echo "Ping Sucessful. The Device will Continue Operating"
sleep 600
else
systemctl reboot
fi
done
The results are the results of the net_loop.sh script are open in another terminal.
Note: I used help from this thread
If minute interval is usable why not use "cron" to start your?
$> crontab –e
or
$> sudo crontab –e

Automatically terminate all nodes after calling roslaunch

I am trying to run several roslaunch files, one after the other, from a bash script. However, when the nodes complete execution, they hang with the message:
[grem_node-1] process has finished cleanly
log file: /home/user/.ros/log/956b5e54-75f5-11e9-94f8-a08cfdc04927/grem_node-1*.log
Then I need to Ctrl-C to get killing on exit for all of the nodes launched from the launch file. Is there some way of causing nodes to automatically kill themselves on exit? Because at the moment I need to Ctrl-C every time a node terminates.
My bash script looks like this, by the way:
python /home/user/git/segmentation_plots/scripts/generate_grem_launch.py /home/user/Data2/Coco 0 /home/user/git/Async_CNN/config.txt
source ~/setupgremsim.sh
roslaunch grem_ros grem.launch config:=/home/user/git/Async_CNN/config.txt
source /home/user/catkin_ws/devel/setup.bash
roslaunch rpg_async_cnn_generator conf_coco.launch
The script setupgremsim.sh sources another catkin workspace.
Many thanks!
Thanks all for your advice. What I ended up doing was this; I launched my ROS Nodes from separate python scripts, which I then called from the bash script. In python you are able to terminate child processes with shutdown. So to provide an example for anyone else with this issue:
bash script:
#!/bin/bash
for i in {0..100}
do
echo "========================================================\n"
echo "This is the $i th run\n"
echo "========================================================\n"
source /home/timo/catkin_ws/devel/setup.bash
python planar_launch_generator.py
done
and then inside planar_launch_generator.py:
import roslaunch
import rospy
process_generate_running = True
class ProcessListener(roslaunch.pmon.ProcessListener):
global process_generate_running
def process_died(self, name, exit_code):
global process_generate_running
process_generate_running = False
rospy.logwarn("%s died with code %s", name, exit_code)
def init_launch(launchfile, process_listener):
uuid = roslaunch.rlutil.get_or_generate_uuid(None, False)
roslaunch.configure_logging(uuid)
launch = roslaunch.parent.ROSLaunchParent(
uuid,
[launchfile],
process_listeners=[process_listener],
)
return launch
rospy.init_node("async_cnn_generator")
launch_file = "/home/user/catkin_ws/src/async_cnn_generator/launch/conf_coco.launch"
launch = init_launch(launch_file, ProcessListener())
launch.start()
while process_generate_running:
rospy.sleep(0.05)
launch.shutdown()
Using this method you could source any number of different catkin workspaces and launch any number of launchfiles.
Try to do this
(1) For each launch you put in a separate shell script. So you have N script
In each script, call the launch file in xterm. xterm -e "roslaunch yourfacnylauncher"
(2) Prepare a master script which calling all N child script in the sequence you want it to be and delay you want it to have.
Once it is done, xterm should kill itself.
Edit. You can manually kill one if you know its gonna hang. Eg below
#!/bin/sh
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
start ROScore using systemd or rc.local using lxtermal or other terminals to avoid accident kill. Then run the part which you think gonna hang or create a problem. Echo->action if necessary
xterm -geometry 80x36+0+0 -e "echo 'uav' | sudo -S dnsmasq -C /dev/null -kd -F 10.5.5.50,10.5.5.100 -i enp59s0 --bind-dynamic" & sleep 15
Stupid OUSTER LIDAR cant auto config like Veloydne and will hang here. other code cant run
killall xterm & sleep 1
Lets just kill it and continuous run other launches
xterm -e "roslaunch '/home/uav/catkin_ws/src/ouster_driver_1.12.0/ouster_ros/os1.launch' os1_hostname:=os1-991907000715.local os1_udp_dest:=10.5.5.1"

How can I improve this bash script?

I'm trying to write a bash script.
The script should check if the MC server is running. If it crashed or stopped it will start the server automatically.
I'll use crontab to run the script every minute. I think I can run it every second it won't stress the CPU too much. I also would like to know when was the server restarted. So I'm going to print the date to the "RestartLog" file.
This is what I have so far:
#!/bin/sh
ps auxw | grep start.sh | grep -v grep > /dev/null
if [ $? != 0 ]
then
cd /home/minecraft/minecraft/ && ./start.sh && echo "Server restarted on: $(date)" >> /home/minecraft/minecraft/RestartLog.txt > /dev/null
fi
I'm just started learning Bash and I'm not sure if this is the right way to do it.
The use of cron is possible, there are other (better) solutions (monit, supervisord etc.). But that is not the question; you asked for "the right way". The right way is difficult to define, but understanding the limits and problems in your code may help you.
Executing with normal cron will happen at most once per minute. That means that you minecraft server may be down 59 seconds before it is restarted.
#!/bin/sh
You should have the #! at the beginning of the line. Don't know if this is a cut/paste problem, but it is rather important. Also, you might want to use #!/bin/bash instead of #!/bin/sh to actually use bash.
ps auxw | grep start.sh | grep -v grep > /dev/null
Some may suggest to use ps -ef but that is a question of taste. You may even use ps -ef | grep [s]tart.sh to prevent using the second grep. The main problem however with this line is that that you are parsing the process-list for a fairly generic start.sh. This may be OK if you have a dedicated server for this, but if there are more users on the server, you run the risk that someone else runs a start.sh for something completely different.
if [ $? != 0 ]
then
There was already a comment about the use of $? and clean code.
cd /home/minecraft/minecraft/ && ./start.sh && echo "Server restarted on: $(date)" >> /home/minecraft/minecraft/RestartLog.txt > /dev/null
It is a good idea to keep a log of the restarts. In this line, you make the execution of the ./start.sh dependent on the fact that the cd succeeds. Also, the echo only gets executed after the ./start.sh exists.
So that leaves me with a question: does start.sh keep on running as long as the server runs (in that case: the ps-test is ok, but the && echo makes no sense, or does start.sh exit while leaving the minecraft-server in the background (in that case the ps-grep won't work correctly, but it makes sense to echo the log record only if start.sh exits correctly).
fi
(no remarks for the fi)
If start.sh blocks until the server exists/crashes, you'd be better off to simply restart it in an infinite loop without the involvement of cron. Simply type in a console (or put into another script):
#!/bin/bash
cd /home/minecraft/minecraft/
while sleep 3; do
echo "$(date) server (re)start" >> restart.log
./start.sh # blocks until server crashes
done
But if it doesn't block (i.e. if start.sh starts the server and then returns, but the server keeps running), you would need to implement a different check to verify if the server is actually still running, other than ps|grep start.sh
PS: To kill the infinite loop you have to Ctrl+C twice: Once to stop ./start.sh and once to exit from the immediate sleep.
You can use monit for this task. See docu. It is available on most linux distributions and has a straightforward config. Find some examples in this post
For your app it will look something like
check process minecraftserver
matching "start.sh"
start program = "/home/minecraft/minecraft/start.sh"
stop program = "/home/minecraft/minecraft/stop.sh"
I wrote this answer because sometimes the most efficient solution is already there and you don't have to code anything. Also follow the suggestions of William Pursell and use the init system of your OS (systemd,upstart,system-v,etc.) to host your scripts.
Find more:
Shell Script For Process Monitoring

How to tell Bash to not stop the simulations when ssh disconnects?

I am running some simulations on another machine via ssh. Here is what I do
ssh username#ipp.ip.ip.ip
Go to the right directory
cd path/to/folder
And then I just call my executable
.\myexecutable.exe
The issue is that every time the ssh disconnect, the simulations stops. How can I make sure the simulations doesn't stop on the other machine? Will I somehow receive potential error messages (assuming the code will crash) once I reconnect (ssh)?
You should launch a screen or tmux to create a terminal from which you can detach, leave running in the background and later reattach.
Further reading:
http://ss64.com/osx/screen.html
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/screen.1.html
You may also want to try out Byobu:
http://byobu.co
run your command as follows : nohup ./myexecutable.exe >nohup.out 2>&1 &
The & is to run the command in the background
The >nohup.out 2>&1 sends your stdout and stderr to nohup.out)
Note the '/' as opposed to '\' - which won't work on osx

Trouble Automating Linux (Specifically Raspbian) Scripts

I've been experimenting with Pis for a little while now and am close to completing my first project, I have all the bits working but I'm struggling to put them all together into an automated process.
Basically I have a Pi setup to run a fbi slideshow from a specific folder and I want it to constantly be looking for a pre established Wifi network and when it finds this network it needs to run an update script. I've got these two bits working.
From here, I want the Pi to be turned on and load straight into fbi whilst running the checking script in the background, if the checking script finds the Wifi network then it will run as normal (preferably without ending the slideshow) and when it's done fbi should have an updated selection of images to run (if a restart of fbi is necessary then so be it).
I'm coming up short on achieving this. I can run one script or the other, and if I automate the checking script (cron hasn't worked though I dare say I'm doing something wrong) with rc.local it just gets stuck in a checking loop before login, which kinda makes sense given the script.
Here's the monitoring script:
#!/bin/bash
while true ; do
if ifconfig wlan0 | grep -q "inet addr:" ; then
echo "Wifi connected!"
echo "Initiating Grive sync!"
(cd /home/pi/images/; ./grive -s Pi_Test -V)
sleep 60
else
echo "Wifi disconnected! Attempting to reconnect now."
ifup --force wlan0
sleep 10
fi
done
and in case it's relevant, here's the command the run the fbi slideshow:
fbi -noverbose -a -t 10 -u /home/pi/images/Pi_Test/*.jpg
I do not have a Pi but I have used cron on my VPS which is running a CentOS, but the overall procedure should be similar.
To have some script to be executed by cron, you need to:
Edit /etc/cron.allow
You need to add in your user id to this file so that you can use crontab.
crontab -e
Use this command to add rules you want to fire.
From your description, it seems to me that you already know the syntax to add rules into cron table.
After that, you can use crontab -l to verify your change.
As for stuck at before login, that is very likely due to the while loop. You might want to get rid of the while and sleep because cron is helping you out by invoking your script periodically.
Therefore the following should not suffer from the stuck issue.
if ifconfig wlan0 | grep -q "inet addr:" ; then
echo "Wifi connected!"
echo "Initiating Grive sync!"
(cd /home/pi/images/; ./grive -s Pi_Test -V)
else
echo "Wifi disconnected! Attempting to reconnect now."
ifup --force wlan0
fi
The trick instead, is to have some line similar to this in your cron table
*/1 * * * * /home/David_Legassick/test.sh
The */1 asks cron to call your script test.sh every minute.

Resources