Background task after logging out - bash

I am trying to make a surveillance camera turn on after a specified amount of time after I leave.
I imagined it to be something like this:
sleep 60 && sudo service motion start &> /dev/null &
but the background task seems to get deleted when I log out. Is there a way to make it stick around even after I leave? AND also to have the root permissions?
EDIT:
Okay I ended up making a script that does it instead of using a single command, it looks about like this:
#!/bin/bash
if (( $UID > 0 )); then
echo "Only root can run this script"
exit 1
fi
if [ -z $1 ]; then
TIMEOUT=30
else
TIMEOUT=$1
fi
sleep $TIMEOUT && service motion start &>/dev/null &
exit 0

use nohup:
sudo nohup service motion start &

In addition to nohup, you can also use screen:
screen
sudo service motion start
Then type CTRL+a then d to detach the screen.
To reattach, you can simply use:
screen -x
For more information:
man screen

There are 2 issues here:
Executing something after you log out. (I guess you are planning to put it in ~/.bash_logout, which is a good idea)
Executing it under sudo, which may be difficult.
Below are the common approaches:
nohup sudo ( sleep 60; service motion start ) &
#Has issues, if sudo authentication is not complete till this point, since background process cannot prompt you for sudo password. Better to call `sudo true` or `sudo echo -n` or similar dumb command, under sudo before calling the actual command.
#You may be tempted to call sudo only for service command, instead of entire command.
However, there is a risk that if sleep interval is long enough, then sudo token may expire.
echo service motion start | sudo at now+1min
#The problem with this command is that the granularity is minute level, not seconds level. Otherwise, this looks clean to me.
Based on your requirement, you can choose either of them, or any other mechanism mentioned in the other answers.

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

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

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.

nohup and enter will stop the process: why?

My script needs root privileges and I want to run it on a remote machine and then be able to turn off my local computer.
So I did:
$ nohup sudo ./myScript arg1 &
... which I always do, but on a different machine where I'm always root, so without sudo. For some reason now it's not working:
nohup sudo ./myScript.sh 1 & //then I press enter twice
[8] 24264
me#my-laptop:~/myFolder$ nohup: ignoring input and appending output to `nohup.out'
[8]+ Stopped nohup sudo ./myScript.sh 1
What am I doing wrong here?
Try this:
sudo nohup ./script
After answering the password prompt, type Ctrl-z to suspend it, and bg to put it into the background.
This is especially helpful if you are half-way through running a long process when you decide it needs to be run in the background.
As mentioned in other answers, if a background process started with nohup tries to read from or write to the terminal, it is put into the "Stopped" state. The sudo process that you're executing tries to read your password from the terminal, so the process is stopped (for some reason, the reading seems to be triggered when Enter is pressed).
So, to avoid this, you ned to make sure to enter your password and become root before nohup is executed. For example, like this:
sudo bash -c 'nohup ./myScript.sh arg1 &'
One option here is use the screen utility. Start screen, run your script, detach using CTRL+A, D. Later, log back in, reconnect to the process by running screen again.

How to switch a sequence of tasks to background?

I'm running two tests on a remote server, here is the command I used several hours ago:
% ./test1.sh; ./test2.sh
The two tests are supposed to run one by one.If the second runs before the first completes, everything will be in ruin, and I'll have to restart the whole procedure.
The dilemma is, these two tasks cost too many hours to complete, and when I prepare to logout the server and wait for the result. I don't know how to switch both of them to background... If I use Ctrl+Z, only the first task will be suspended, while the second starts doing nothing useful while wiping out current data.
Is it possible to switch both of them to background, preserving their orders? Actually I should make these two tasks in the same process group like (./test1.sh; ./test2.sh) &, but sadly, the first test have run several hours, and it's quite a pity to restart the tests.
An option is to kill the second test before it starts, but is there any mechanism to cope with this?
First rename the ./test2.sh to ./test3.sh. Then do [CTRL+Z], followed by bg and disown -h. Then save this script (test4.sh):
while :; do
sleep 5;
pgrep -f test1.sh &> /dev/null
if [ $? -ne 0 ]; then
nohup ./test3.sh &
break
fi
done
then do: nohup ./test4.sh &.
and you can logout.
First, screen or tmux are your friends here, if you don't already work with them (they make remote machine work an order of magnitude easier).
To use conditional consecutive execution you can write:
./test1.sh && ./test2.sh
which will only execute test2.sh if test1.sh returns with 0 (conventionally meaning: no error). Example:
$ true && echo "first command was successful"
first command was successful
$ ! true && echo "ain't gonna happen"
More on control operators: http://www.humbug.in/docs/the-linux-training-book/ch08s01.html

Resources