(Sorry for bad English, I'm German)
I'm trying (without success) to make my own program start automatically after booting (on a raspberry with raspian).
This is my script: (Note: You have to run this program with root privileges) (Note#2: There must be an empty file called "/home/testLog.txt" with write privileges for every user):
rm /etc/init.d/RMStart
echo "
#! /bin/sh
### BEGIN INIT INFO
# Provides: bla1
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: bla2
# Description: bla3
### END INIT INFO
#Switch case for the first parameter
case \"\$1\" in
start)
echo \"Start\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
stop)
echo \"Stop\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
restart)
echo \"Restart\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
*)
echo \"something else\" >> /home/testLog.txt
;;
esac
exit 0
" >> /etc/init.d/RMStart
chmod +x /etc/init.d/RMStart
update-rc.d RMStart remove #Remove older versions of this program ... in theory
update-rc.d RMStart defaults #Install new version of this program ... in theory
I've rebooted the raspberry, but the file /home/testLog.txt is still empty.
However, if I run the command: "/etc/init.d/RMStart" or "/etc/init.d/RMStart start" there is a new entry in /home/testLog.txt.
I would be thankful if anyone knows why the file /home/testLog.txt is still empty and how I could fix that.
Update:
I've tried a new installation script:
#RMS install script
chmod +x botComp.sh
rm /home/pi/RMS
pkill RMS
./botComp.sh
cp RMS /home/pi
chmod +x /home/pi/RMS
rm /etc/init.d/startRMS
sudo echo "#!/bin/sh
### BEGIN INIT INFO
# Provides: fqew
# Required-Start:
# Required-Stop:
# Default-Start: 3 4 5
# Default-Stop: 0 1 6
# Short-Description: sfwef
# Description: gfewf
### END INIT INFO
# Actions
case \"\$1\" in
start)
# START
su pi sh -c \" /home/pi/RMS \"
;;
stop)
# STOP
;;
restart)
# RESTART
;;
esac
exit 0 " >> /etc/init.d/startRMS
chmod +x /etc/init.d/startRMS
update-rc.d startRMS remove
update-rc.d startRMS defaults
The only difference I can see is the name of the script (/etc/init.d/startRMS instead of /etc/init.d/RMStart).
The script works, RMS is running.
It's not really a problem, but the script outputs:
insserv: script RMStart: service F already provided!
insserv: script RMStart: service F already provided!
I've added the line system("runlevel >> /home/pi/runlevelLog.txt"); In the program (RMS) but the content of /home/pi/runlevelLog.txt is: "unknown".
Does RMS start at runlevel 3? How I can I verify this? (I think runlevel 3 is ideal, because RMS needs Network Connection.) Thank you for your help.
is /etc/init.d/RMStart definitely being executed on reboot? use ls -lu to check the last time the file was accessed, wait a minute before rebooting, and repeat the command once you're back up. If the access time hasn't moved on then your script isn't being run which would explain the empty file as your script looks Ok.
You should also double check that update-rc.d has created symbolic links to your script in the appropriate run level directives e.g. does /etc/rc2.d/RMStart exist?
Another sanity check would be running your script using the symbolic links in the above directory rather than from /etc/init.d e.g. does /etc/rc2.d/RMStart
generate output in /home/testLog.txt?
Let me know what you find and we'll take it from there.
EDIT: attempting to replicate..
Well I managed to find my PI; the good news is that neither of us are going mad because it worked perfectly first time as we both believed it should.
I took a copy of your file, and I wrote a quick script (x) to check the exit codes from update-rc.d just to make 100% sure it wasn't complaining about anything.
Hopefully you can follow what I did in the screen shot above - I replicated the steps you followed almost exactly with a bit of extra checking along the way. The script certainly works as designed when called directly.
I then rebooted immediately and checked testLog.txt as soon soon as the system was up. You can see two entries in the file which is expected behaviour as init would have run /etc/rc6.d/K01RMStart as the system went down for reboot, and /etc/rc5.d/S01RMStart as it came up again.
Unfortunately this doesn't help you much.....
The only significant differnce between our tests was that I ran everything as root rather than using sudo. This shouldn't make a difference but the next logical thing for you to try is probably copying my test exactly and seeing if it works for you?
Not that this should be at all significant but I'm running Raspbian 8 (kernel 4.1.13+).
EDIT2: awesome... great stuff. I'd still like to know what the problem was but the main thing in that it's working.
System V based distributions will usually start in either level 3 or level 5, the difference being that level 5 will start the GUI whereas level 3 will start in text mode, their default runlevel is controlled by a line in /etc/inittab.
Debian(Raspian) distros are a bit different - (https://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit). They make no distinction between run levels 2-5 and leave it up the user to configure them to suit their requirements by adding services using the mechanism that's been causing us pain for the last 24 hours. They always start in level 5 unless a "init=" kernel boot parameter has been set, which you can do either at boot time or with a tool like bum or raspi-config.
The command runlevel will tell you the current level on raspian.
You can change the runlevel on the fly with telinit new_runlevel if you need to, but whatever you do, don't set the default runlevel to 0 :-)
Related
I have a Raspberry Pi 3 - Model B, with Raspbian jessie operation system.
Im trying to open "chromium" on startup.
i wrote a simple script:
#!/bin/bash
/usr/bin/chromium-browser --noerordialogs --disable-session-crashed-bubble --disable-infobars --kiosk http://www.google.com
exit 0
I can run the script manually and it works perfect.
I read about a lot of various ways to run this script on startup.
I have tried:
adding this line #reboot path/to/my/script to crontab -e file with no success.
Also i have tried to edit /etc/rc.local file by adding this line:
#!/bin/sh -e
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
/home/pi/Desktop/script1.sh& <-------- THIS LINE
fi
exit 0
I have checked that the script is executable and rc.local too:
rwxrwxrwx 1 pi pi script1.sh
rwxr-xr-x 1 root root rc.local
I can see script1.sh tesk on my Task Manger (it runs as root) but nothing happen.
The default user is Pi and i log as a Pi user and not as root, maybe this is the problem?
Can someone explain me what is the problom and why i can see the script only in the Task Manager? what should i do ?
TNX!
UPDATE
i have changed the rc.local to be like:
!/bin/sh -e
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
su - pi -c "/usr/bin/chromium-browser --noerordialogs --disable-session-crashed-bubble --disable-infobars --kiosk http://www.google.com &"
fi
exit 0
still does not work for me :|
Check out the verified answer on this question...
Running Shell Script after boot on Raspberry PI
Looks like you need to run the script as the user pi.
su - pi -c "/usr/bin/chromium-browser --noerordialogs --disable-session-crashed-bubble --disable-infobars --kiosk http://www.google.com &"
EDIT: I missed the & at the end of the command.
I did a small hack...
I added this line #lxterminal to the end of this file:
nano .config/lxsession/LXDE-pi/autostart
It will auto-start terminal on boot.
Then I edited $ sudo nano .bashrc file.
At the end of the file, I added my path to my script.
./home/pi/Desktop/script.sh
It means that:
The terminal will open every time you boot your Raspberry Pi (first command).
Every time that terminal runs, my script will run also (second command)
It does work for me.
TNX for the help :)
Adding the shell script path directly to ~/.config/lxsession/LXDE-pi/autostart (not to ~/.bashrc) works better.
Namely it does not execute the command every terminal session (including ssh).
Try this in the autostart file instead:
#sh /home/pi/Desktop/script.sh &
I know, I know. These posts appear all the dang time. I swear, my machine/code is an exception to what most people are trying to accomplish/what problem(s) they're running into when attempting to set up these seemingly simple scripts.
I have a file named IPdetermination.rb on my Raspberry Pi (running the Raspbian OS) that basically uses the rest-client ruby gem to perform a http POST with JSON. Such is the code:
#sends a message to slack using incoming-webhook that identifies that
#host machine's name and ip address.
require 'rest-client'
address = Socket.ip_address_list.detect {|x| x.ipv4_private?}.ip_address
name = Socket.gethostname
if name.include? '.' then name = name.slice(0..name.index('.') - 1) end
payload = {text: "*Device:* `#{name}`\n *IP:* `#{address}`"}.to_json
RestClient.post 'https://hooks.slack.com/services/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', payload
Note that this does work. So, in fact, does this bash script, which is stored under /etc/init.d
#! /bin/bash
# /etc/init.d/ip_addr
### BEGIN INIT INFO
# Provides: ip_addr
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: ip address locator
# Description: sends hostname's ip address on private slack channel
### END INIT INFO
exec ruby ~/Documents/coding/ruby/IPdetermination.rb
exit 0
They both work when manually executed, successfully posting a message on Slack. Note that I have both attached LSB comments to the ip_addr script and configured the file such so that running ls -l returns -rwxr-xr-x 1 root root 413 Dec 30 03:39 ip_addr. Running chkconfig --list correctly displays ip_addr 0:off 1:off 2:on 3:on 4:on 5:on 6:off.
Yet
It doesn't work! Rebooting the system does not seem to run the script. My only theory could be that the POSTing could be faulty upon reboot, yet I cannot determine whether or not this is the source of the problem. What do I do?
Edit: Changing the Required-Start: and Required-Stop: to also include the boot facilities $network and $named did not work either.
afaik scripts under /etc/init.d/ are not executed upon reboot. there need to be at least symbolic links set in the runlevel directories /etc/rc*.d/ prefixed with an S if you want to run a script upon boot when entering the specific runlevel. if prefixed with K it means something like kill so it won't be executed upon boot or gets killed on shutdown. numerical values appended to these main prefix let you define an order in which the scripts are run on boot.
so if you want to run ascript on boot when entering run level two you need to do sth like:
$ ln -s /etc/init.d/ascript /etc/rc2.d/S01ascript
this will cause ascript to be run first when entering runlevel 2.
any update mechanism like update-rc.d or systemctl enable ... will just set such links to make scripts avaiable/called on boot.
hope this helps. regards
Ok, finally found the problem, thanks to users like #tasasaki. What happened was I added a line within /etc/rc.local that called my bash script with a full path name, as well as editing the bash script to have full path names. Also, within rc.local, I didn't realize exit 0 is only put down once, so I put my code after the exit 0. Moving it up probably helped as well. Should anyone find this, hope it helps!
I want to run simple unmount command before starting my "file-system" service on my node.
Is there any way to call bash script as cluster service?
You can run any script as a cluster service. The script needs to be LSB compliant: i.e. needs to know start, stop, restart, status, etc. I usually copy something simple from /etc/init.d and modify it for myself.
Put the script in /etc/ha.d/resource.d
Test it from command line
# sh /etc/ha.d/resource.d/start (see if it unmounts)
Now if you haven't already, create resource group. Add in all your resources into the same group. Then add your new script in the resource group. You can configure constraints so that all resources depend on your first application resource to run first.
That's about it. You don't need to actually have anything configured for stop and status except "exit" since you just want your script to run once (to unmount)
Here is a script that might work in /etc/ha.d/resource.d
#!/bin/sh
#
# description: testapp auto start-stop script.
#
. /etc/rc.status
case "$1" in
start)
umount [filesystem]
;;
stop)
;;
reload*|restart*|force-reload*)
;;
status)
;;
*)
echo "options: start|stop|reload|restart|force-reload|status"
exit 1
;;
esac
exit
Hope that helps
I have an outline of my steps for building clusters plus an ebook here:
http://geekswing.com/geek/building-a-two-node-sles11-sp2-linux-cluster-on-vmware/
I am starting ftam server (ft820.rc on CentOS 5) using bash version bash 3.0 and I am having an issue with starting it from the script, namely in the script I do
ssh -nq root#$ip /etc/init.d/ft820.rc start
and the script won't continue after this line, although when I do on the machine defined by $ip
/etc/init.d/ft820.rc start
I will get the prompt back just after the service is started.
This is the code for start in ft820.rc
SPOOLPATH=/usr/spool/vertel
BINPATH=/usr/bin/osi/ft820
CONFIGFILE=${SPOOLPATH}/ffs.cfg
# Set DBUSERID to any value at all. Just need to make sure it is non-null for
# lockclr to work properly.
DBUSERID=
export DBUSERID
# if startup requested then ...
if [ "$1" = "start" ]
then
mask=`umask`
umask 0000
# startup the lock manager
${BINPATH}/lockmgr -u 16
# update attribute database
${BINPATH}/fua ${CONFIGFILE} > /dev/null
# clear concurrency locks
${BINPATH}/finit -cy ${CONFIGFILE} >/dev/null
# startup filestore
${BINPATH}/ffs ${CONFIGFILE}
if [ $? = 0 ]
then
echo Vertel FT-820 Filestore running.
else
echo Error detected while starting Vertel FT-820 Filestore.
fi
umask $mask
I repost here (on request of #Patryk) what I put in the comments on the question:
"is it the same when doing the ssh... in the commandline? ie, can you indeed connect without entering a password, using the pair of private_local_key and the corresponding public_key that you previously inserted in the destination root#$ip:~/.ssh/authorized_keys file ? – Olivier Dulac 20 hours ago "
"you say that, at the commandline (and NOT in the script) you can ssh root#.... and it works without asking for your pwd ? (ie, it can then be run from a script?) – Olivier Dulac 20 hours ago "
" try the ssh without the '-n' and even without -nq at all : ssh root#$ip /etc/init.d/ft820.rc start (you could even add ssh -v , which will show you local (1:) and remote (2:) events in a very verbose way, helping in knowing where it gets stuck exactly) – Olivier Dulac 19 hours ago "
"also : before the "ssh..." line in the script, make another line with, for example: ssh root#ip "set ; pwd ; id ; whoami" and see if that works and shows the correct information. This may help be sure the ssh part is working. The "set" part will also show you the running shell (ex: if it contains BASH= , you're running bash. Otherwise SHELL=... should give a good hint (sometimes not correct) about which shell gets invoked) – Olivier Dulac 19 hours ago "
" please try without the '-n' (= run in background and wait, instead of just run and then quit). It it doesn't work, try adding -t -t -t (3 times) to the ssh, to force it to allocate a tty. But first, please drop the '-n'. – Olivier Dulac 18 hours ago "
Apparently what worked was to add the -t option to the ssh command. (you can go up to put '-t -t -t' to further force it to try to allocate the tty, depending on the situation)
I guess it's because the invoked command expected to be run within an interactive session, and so needed a "tty" to be the stdout
A possibility (but just a wild guess) : the invoked rc script outputs information, but in a buffered environment (ie, when not launched via your terminal), the calling script couldn't see enough lines to fill the buffer and start printing anything out (like when you do a "grep something | somethings else" in a buffered environment and ctrl+c before the buffer was big enough to display anything : you end up thinking no lines were foudn by the grep, whereas there was maybe a few lines already in the buffer). There is tons to be said about buffering, and I am just beginning to read about it all. forcing ssh to allocate a tty made the called command think it was outputting to a live terminal session, and that may have turned off the buffering and allowed the result to show. Maybe in the first case, it worked too, but you could never see the output?
I have a java program that stops often due to errors which is logged in a .log file. What can be a simple shell script to detect a particular text in the last/latest line say
[INFO] Stream closed
and then run the following command
java -jar xyz.jar
This should keep on happening forever(possibly after every two minutes or so) because xyz.jar writes the log file.
The text stream closed can arrive a lot of times in the log file. I just want it to take an action when it comes in the last line.
How about
while [[ true ]];
do
sleep 120
tail -1 logfile | grep -q "[INFO] Stream Closed"
if [[ $? -eq 1 ]]
then
java -jar xyz.jar &
fi
done
There may be condition where the tailed last log "Stream Closed" is not the real last log and the process is still logging the messages. We can avoid this condition by checking if the process is alive or not. If the process exited and the last log is "Stream Closed" then we need to restart the application.
#!/bin/bash
java -jar xyz.jar &
PID=$1
while [ true ]
do
tail -1 logfile | grep -q "Stream Closed" && kill -0 $PID && sleep 20 && continue
java -jar xyz.jar &
PID=$1
done
I would prefer checking whether the corresponding process is still running and restart the program on that event. There might be other errors that cause the process to stop. You can use a cronjob to periodically (like every minute) perform such a check.
Also, you might want to improve your java code so that it does not crash that often (if you have access to the code).
i solved this using a watchdog script that checks directly (grep) if program(s) is(are) running. by calling watchdog every minute (from cron under ubuntu), i basically guarantee (programs and environment are VERY stable) that no program will stay offline for more than 59 seconds.
this script will check a list of programs using the name in an array and see if each one is running, and, in case not, start it.
#!/bin/bash
#
# watchdog
#
# Run as a cron job to keep an eye on what_to_monitor which should always
# be running. Restart what_to_monitor and send notification as needed.
#
# This needs to be run as root or a user that can start system services.
#
# Revisions: 0.1 (20100506), 0.2 (20100507)
# first prog to check
NAME[0]=soc_gt2
# 2nd
NAME[1]=soc_gt0
# 3rd, etc etc
NAME[2]=soc_gp00
# START=/usr/sbin/$NAME
NOTIFY=you#gmail.com
NOTIFYCC=you2#mail.com
GREP=/bin/grep
PS=/bin/ps
NOP=/bin/true
DATE=/bin/date
MAIL=/bin/mail
RM=/bin/rm
for nameTemp in "${NAME[#]}"; do
$PS -ef|$GREP -v grep|$GREP $nameTemp >/dev/null 2>&1
case "$?" in
0)
# It is running in this case so we do nothing.
echo "$nameTemp is RUNNING OK. Relax."
$NOP
;;
1)
echo "$nameTemp is NOT RUNNING. Starting $nameTemp and sending notices."
START=/usr/sbin/$nameTemp
$START 2>&1 >/dev/null &
NOTICE=/tmp/watchdog.txt
echo "$NAME was not running and was started on `$DATE`" > $NOTICE
# $MAIL -n -s "watchdog notice" -c $NOTIFYCC $NOTIFY < $NOTICE
$RM -f $NOTICE
;;
esac
done
exit
i do not use the log verification, though you could easily incorporate that into your own version (just change grep for log check, for example).
if you run it from command line (or putty, if you are remotely connected), you will see what was working and what wasnt. have been using it for months now without a hiccup. just call it whenever you want to see what's working (regardless of it running under cron).
you could also place all your critical programs in one folder, do a directory list and check if every file in that folder has a program running under the same name. or read a txt file line by line, with every line correspoding to a program that is supposed to be running. etcetcetc
A good way is to use the awk command:
tail -f somelog.log | awk '/.*[INFO] Stream Closed.*/ { system("java -jar xyz.jar") }'
This continually monitors the log stream and when the regular expression matches its fires off whatever system command you have set, which is anything you would type into a shell.
If you really wanna be good you can put that line into a .sh file and run that .sh file from a process monitoring daemon like upstart to ensure that it never dies.
Nice and clean =D