Run script with rc.local: script works, but not at boot - linux

I have a node.js script which need to start at boot and run under the www-data user. During development I always started the script with:
su www-data -c 'node /var/www/php-jobs/manager.js
I saw exactly what happened, the manager.js works now great. Searching SO I found I had to place this in my /etc/rc.local. Also, I learned to point the output to a log file and to append the 2>&1 to "redirect stderr to stdout" and it should be a daemon so the last character is a &.
Finally, my /etc/rc.local looks like this:
#!/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.
su www-data -c 'node /var/www/php-jobs/manager.js >> /var/log/php-jobs.log 2>&1 &'
exit 0
If I run this myself (sudo /etc/rc.local): yes, it works! However, if I perform a reboot no node process is running, the /var/log/php-jobs.log does not exist and thus, the manager.js does not work. What is happening?

In this example of a rc.local script I use io redirection at the very first line of execution to my own log file:
#!/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.
exec 1>/tmp/rc.local.log 2>&1 # send stdout and stderr from rc.local to a log file
set -x # tell sh to display commands before execution
/opt/stuff/somefancy.error.script.sh
exit 0

On some linux's (Centos & RH, e.g.), /etc/rc.local is initially just a symbolic link to /etc/rc.d/rc.local. On those systems, if the symbolic link is broken, and /etc/rc.local is a separate file, then changes to /etc/rc.local won't get seen at bootup -- the boot process will run the version in /etc/rc.d. (They'll work if one runs /etc/rc.local manually, but won't be run at bootup.)
Sounds like on dimadima's system, they are separate files, but /etc/rc.d/rc.local calls /etc/rc.local
The symbolic link from /etc/rc.local to the 'real' one in /etc/rc.d can get lost if one moves rc.local to a backup directory and copies it back or creates it from scratch, not realizing the original one in /etc was just a symbolic link.

I ended up with upstart, which works fine.

In Ubuntu I noticed there are 2 files. The real one is /etc/init.d/rc.local; it seems the other /etc/rc.local is bogus?
Once I modified the correct one (/etc/init.d/rc.local) it did execute just as expected.

You might also have made it work by specifying the full path to node. Furthermore, when you want to run a shell command as a daemon you should close stdin by adding 1<&- before the &.

I had the same problem (on CentOS 7) and I fixed it by giving execute permissions to /etc/local:
chmod +x /etc/rc.local

if you are using linux on cloud, then usually you don't have chance to touch the real hardware using your hands. so you don't see the configuration interface when booting for the first time, and of course cannot configure it. As a result, the firstboot service will always be in the way to rc.local. The solution is to disable firstboot by doing:
sudo chkconfig firstboot off
if you are not sure why your rc.local does not run, you can always check from /etc/rc.d/rc file because this file will always run and call other subsystems (e.g. rc.local).

I got my script to work by editing /etc/rc.local then issuing the following 3 commands.
sudo mv /filename /etc/init.d/
sudo chmod +x /etc/init.d/filename
sudo update-rc.d filename defaults
Now the script works at boot.

I am using CentOS 7.
$ cd /etc/profile.d
$ vim yourstuffs.sh
Type the following into the yourstuffs.sh script.
type whatever you want here to execute
export LD_LIBRARY_PATH=/usr/local/cuda-7.0/lib64:$LD_LIBRARY_PATH
Save and reboot the OS.

I have used rc.local in the past. But I have learned from my experience that the most reliable way to run your script at the system boot time is is to use #reboot command in crontab. For example:
#reboot path_to_the_start_up_script.sh

This is most probably caused by a missing or incomplete PATH environment variable.
If you provide full absolute paths to your executables (su and node) it will work.

It is my understanding that if you place your script in a certain RUN Level, you should use ln -s to link the script to the level you want it to work in.

first make the script executable using
sudo chmod 755 /path/of/the/file.sh
now add the script in the rc.local
sh /path/of/the/file.sh
before exit 0
in the rc.local,
next make the rc.local to executable with
sudo chmod 755 /etc/rc.local
next to initialize the rc.local use
sudo /etc/init.d/rc.local start
this will initiate the rc.local
now reboot the system.
Done..

I found that because I was using a network-oriented command in my rc.local, sometimes it would fail. I fixed this by putting sleep 3 at the top of my script. I don't know why but it seems when the script is run the network interfaces aren't properly configured or something, and this just allows some time for the DHCP server or something. I don't fully understand but I suppose you could give it a try.

I had exactly same issue, the script was running fine locally but when I reboot/power-on it was not.
I resolved the issue by changing the file path. Basically need to give the complete path in the script. While running locally, file can be accessed but when running on reboot, local path will not be understood.

1 Do not recommend using root to run the apps such as node app.
Well you can do it but may catch more exceptions.
2 The rc.local normally runs as root user.
So if the your script should runs as another user such as www U should make sure the PATH and other environment is ok.
3 I find a easy way to run a service as a user:
sudo -u www -i /the/path/of/your/script
Please prefer the sudo manual~
-i [command]
The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a loginshell...

rc.local only runs on startup. If you reboot and want the script to execute, it needs to go into the rc.0 file starting with the K99 prefix.

Related

How to Run Shell Script at start in VM Virtualbox Ubuntu 16.04

I am trying to run a shell script which runs at system login. To try, I used an example script, which has two lines
#!/bin/bash
echo “Hello World”
I Followed all the instructions mentioned on this website http://www.cyberciti.biz/tips/linux-how-to-run-a-command-when-boots-up.html
Even I did some steps such as editing /etc/rc.local, but still when I login, I do not see Hello world output running on terminal.
Can anyone please explain what is wrong here or may be I am missing something?
Looks to me like Ubuntu 16.04 is a systemd system.
Which means you should create a systemd service to run whatever you'd like # startup.
Look here https://wiki.ubuntu.com/SystemdForUpstartUsers#Example_Systemd_service
After you made your service, use systemctl to enable it on boot for systemd.
sudo systemctl enable mycustom.service
To start the service.
sudo systemctl start mycustom.service
You can also schedule a cron job to run once after the reboot command. The line will need "#reboot root /path/script.sh" You can specify whatever user you want to run the script. To make the result easier to find, you might make that second line something like
echo "Hello World" > /root/hello.txt
Add the line in /etc/profile under echo command as follows
echo “Hello World”
Then execute the following command
source /etc/profile

How to execute script after system reboot by using kickstart

I'm using PXE to install ISO. There are two scripts for environment configuration, I want to added them in kickstart file, so the environment will be setup completely and automatically after the system installed.
However, my situation is:
Script 1 must reboot (has been added in script1.sh)
Script 2 depends on script 1
Here part of kickstart file:
...
...
%post
wget http://xxx/script1.sh
wget http://xxx/script2.sh
sh -x script1.sh | tee script1.log
sh -x script2.sh | tee script2.log
%end
So, is there anyway that script 2 can be executed after system reboot by using kickstart file? Or the other way, just executed the script 2 once after reboot.
Thanks.
The way I have done this is to make a startup script that calls secondary script(s), which in your case are script1.sh and script2.sh.
Here is one reference about configuring RHEL 6 Runlevels and Services. Alternatively, if have access to an existing RHEL/CentOS system you could browse /etc/init.d/ and copy one of the simpler startup scripts there as the basis for your own.
To put this all together, you'll need to:
In your kickstart file
Add an additional wget call to download the startup script you created.
You'll need to copy/move the startup script to /etc/init.d . Keep in mind that %post is run in a chroot environment.
Enable the startup script on boot with chkconfig.
In your startup script
Upon successful completion of script2.sh, disable the startup script with another chkconfig *service_name* off so it isn't run on future reboots.

Linux Debian Run commands at boot in init script

I'm new to Linux (obviously) and I need to run some commands whenever my Linux server boots without typing them into the console manually.
I have this file called overpass.conf that runs on boot perfectly:
description 'Overpass API dispatcher daemon'
env DB_DIR=/var/www/osm/db/
env EXEC_DIR=/var/www/osm/
start on (local-filesystems and net-device-up)
stop on runlevel [!2345]
pre-start script
rm $DB_DIR/osm3s* || true
rm /dev/shm/osm3s* || true
end script
exec $EXEC_DIR/bin/dispatcher --osm-base --db-dir=$DB_DIR
However, I want to also run the following:
cp -pR "/root/osm-3s_v0.7.4/rules" "/var/www/osm/db/"
nohup /var/www/osm/bin/dispatcher --areas --db-dir="/var/www/osm/db/" &
chmod 666 "/var/www/osm/db/osm3s_v0.7.4_areas"
nohup /var/www/osm/bin/rules_loop.sh "/var/www/osm/db/" &
I have tried adding them to the bottom of the file, adding exec to the execution commands and even tried removing the quotes, then testing with start overpass but it throws errors if I add any commands to the original ones.
How can I go about executing those 4 commands after the original ones? I'm a noob in distress. Thanks!
Edit
I solved it with these commands:
vi /etc/init.d/mystartup.sh
-Add commands to the script
chmod +x /etc/init.d/mystartup.sh
update-rc.d mystartup.sh defaults 99
There's also /etc/rc.local that is executed at the end of the boot process.

Why this shell won't work if it's called from rc.local but SSH?

I made this shell script
/var/start-app.sh
#!/bin/sh
# file-name: app-start.sh
cd /var/www/html/app
bundle exec rake sunspot:solr:start RAILS_ENV=production
unicorn_rails -c config/unicorn.rb -E production -D
If I type /var/start-app.sh in SSH. It triggers, and everything works fine.
Then I did put sh /var/start-app.sh in the end line of /etc/rc.d/rc.local in order to make it run on Server's start up.
But this never work. Why? and How can I enable that?
From SSH, I called it with root permission.
Is that why? If so, how can I give root permission to rc.local?
Looks like starting services from rc.local is not the best practice http://bencane.com/2011/12/30/when-its-ok-and-not-ok-to-use-rc-local/. You would be better writing an init script :
http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/sysinit.html

How to run a shell script at startup

On an Amazon S3 Linux instance, I have two scripts called start_my_app and stop_my_app which start and stop forever (which in turn runs my Node.js application). I use these scripts to manually start and stop my Node.js application. So far so good.
My problem: I also want to set it up such that start_my_app is run whenever the system boots up. I know that I need to add a file inside init.d and I know how to symlink it to the proper directory within rc.d, but I can't figure out what actually needs to go inside the file that I place in init.d. I'm thinking it should be just one line, like, start_my_app, but that hasn't been working for me.
First create your startup script # /home/user/startup.sh, and make it executable
chmod +x /home/user/startup.sh
Then set a crontab for it:
$ crontab -e
#reboot /home/user/startup.sh
Now your your startup.sh script will run at every start.
The file you put in /etc/init.d/ have to be set to executable with:
chmod +x /etc/init.d/start_my_app
As pointed out by #meetamit, if it still does not run you might have to create a symbolic link to the file in /etc/rc.d/
ln -s /etc/init.d/start_my_app /etc/rc.d/
Please note that on the latest versions of Debian, this will not work as your script will have to be LSB compliant (provide at least the following actions: start, stop, restart, force-reload, and status):
https://wiki.debian.org/LSBInitScripts
As a note, you should always use the absolute path to files in your scripts instead of the relative one, it may solve unexpected issues:
/var/myscripts/start_my_app
Finally, make sure that you included the shebang on top of the file:
#!/bin/sh
A simple approach is to add a line in /etc/rc.local :
/PATH/TO/MY_APP &
or if you want to run the command as a special user :
su - USER_FOOBAR -c /PATH/TO/MY_APP &
(the trailing ampersand backgrounds the process and allows the rc.local to continue executing)
If you want a full init script, debian distro have a template file, so :
cp /etc/init.d/skeleton /etc/init.d/your_app
and adapt it a bit.
This is the way I do it on Red Hat Linux systems.
Put your script in /etc/init.d, owned by root and executable. At the top of the script, you can give a directive for chkconfig. Example, the following script is used to start a Java application as user oracle.
The name of the script is /etc/init.d/apex
#!/bin/bash
# chkconfig: 345 99 10
# Description: auto start apex listener
#
case "$1" in
'start')
su - oracle -c "cd /opt/apex ; java -jar apex.war > logs/apex.log 2>logs/apex_error.log &";;
'stop')
echo "put something to shutdown or kill the process here";;
esac
This says that the script must run at levels 3, 4, and 5, and the priority for start/stop is 99 and 10.
Then, as user root you can use chkconfig to enable or disable the script at startup:
chkconfig --list apex
chkconfig --add apex
And you can use service start/stop apex.
Enter cron using sudo:
sudo crontab -e
Add a command to run upon start up, in this case a script:
#reboot sh /home/user/test.sh
Save:
Press ESC then :x to save and exit, or hit ESC then ZZ (that's shift+zz)
Test Test Test:
Run your test script without cron to make sure it actually works.
Make sure you saved your command in cron, use sudo crontab -e
Reboot the server to confirm it all works sudo #reboot
Just have a line added to your crontab..
Make sure the file is executable:
chmod +x /path_to_you_file/your_file
To edit crontab file:
crontab -e
Line you have to add:
#reboot /path_to_you_file/your_file
That simple!
Another option is to have an #reboot command in your crontab.
Not every version of cron supports this, but if your instance is based on the Amazon Linux AMI then it will work.
Edit the rc.local file using nano or gedit editor and add your scripts in it. File path could be /etc/rc.local or /etc/rc.d/rc.local.
sudo nano /etc/rc.local
This is the edit:
#!/bin/sh
/path-to-your-script/your-scipt-name.sh
once done press ctrl+o to update, pressEnter then ctrl+x.
Make the file executable.
sudo chmod 755 /etc/rc.local
Then initiate the rc-local service to run script during boot.
sudo systemctl start rc-local
You can do it :
chmod +x PATH_TO_YOUR_SCRIPT/start_my_app
then use this command
update-rc.d start_my_app defaults 100
Please see this page on Cyberciti.
Many answers on starting something at boot, but often you want to start it just a little later, because your script depends on e.g. networking. Use at to just add this delay, e.g.:
at now + 1 min -f /path/yourscript
You may add this in /etc/rc.local, but also in cron like:
# crontab -e
#reboot at now + 1 min -f /path/yourscript
Isn't it fun to combine cron and at? Info is in the man page man at.
As for the comments that #reboot may not be widely supported, just try it. I found out that /etc/rc.local has become obsolete on distros that support systemd, such as ubuntu and raspbian.
The absolute easiest method if all you want to run is a simple script, (or anything) is if you have a gui to use system > preferences then startup apps.
just browse to the script you want and there you go. (make script executable)
This simple solution worked for me on an Amazon Linux instance running CentOS.
Edit your /etc/rc.d/rc.local file and put the command there. It is mentioned in this file that it will be executed after all other init scripts. So be careful in that regards. This is how the file looks for me currently.. Last line is the name of my script.
Create your own /init executable
This is not what you want, but it is fun!
Just pick an arbitrary executable file, even a shell script, and boot the kernel with the command line parameter:
init=/path/to/myinit
Towards the end of boot, the Linux kernel runs the first userspace executable at the given path.
Several projects provide popular init executables used by major distros, e.g. systemd, and in most distros init will fork a bunch of processes used in normal system operation.
But we can hijack /init it to run our own minimal scripts to better understand our system.
Here is a minimal reproducible setup: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/f96d4d55c9caa7c0862991025e1291c48c33e3d9/README.md#custom-init
I refered to this blog, always sound a good choice
https://blog.xyzio.com/2016/06/14/setting-up-a-golang-website-to-autorun-on-ubuntu-using-systemd/
vim /lib/systemd/system/gosite.service
Description=A simple go website
ConditionPathExists=/home/user/bin/gosite
[Service]
Restart=always
RestartSec=3
ExecStart=/home/user/bin/gosite
[Install]
WantedBy=multi-user.target
systemctl enable gosite.service
multi ways to finish it:
crontab
rc.local
init.d
systemd
For Debian 9 see https://askubuntu.com/questions/228304/how-do-i-run-a-script-at-start-up. It is helped me. Short version for Debian 9:
add commands (as root) to /etc/rc.local
/path_to_file/filename.sh || exit 1 # Added by me
exit 0
Probably, /path_to_file/filename.sh should be executable (I think so).
In Lubuntu I had to deal with the opposite situation. Skype start running after booting and I found in ~/.config/autostart/ the file skypeforlinux.desktop. The content of the file is as follows:
[Desktop Entry]
Name=Skype for Linux
Comment=Skype Internet Telephony
Exec=/usr/bin/skypeforlinux
Icon=skypeforlinux
Terminal=false
Type=Application
StartupNotify=false
X-GNOME-Autostart-enabled=true
Deleting this file helped me.
Here is a simpler method!
First: write a shell script and save it a .sh
here is an example
#!/bin/bash
Icoff='/home/akbar/keyboardONOFF/icon/Dt6hQ.png'
id=13
fconfig=".keyboard"
echo "disabled" > $fconfig
xinput float $id
notify-send -i $Icoff "Internal Keyboard disabled";
this script will disable the internal keyboard at startup.
Second: Open the application " Startup Application Preferences"
enter image description here
enter image description here
Third: click Add.
fourth: in the NAME section give a name.
fifth: In the command section browse to your .sh .
sixth: edit your command section to:
bash <space> path/to/file/<filename>.sh <space> --start
seventh: click Add. Thats it! Finished!
Now confirm by rebooting your pc.
cheers!
Add your script to /etc/init.d/ directory
Update your rc run-levels:
$ update-rc.d myScript.sh defaults NN where NN is the order in which it should be executed. 99 for example will mean it would be run after 98 and before 100.
Painless, easiest and the most universal method is simply
executing it with ~.bash_profile or ~.profile (if you don't have bash_profile file).
Just add the execution command at the bottom of that file and it will be executed when system started.
I have this one at the bottom an example;
~\Desktop\sound_fixer.sh
Working with Python 3 microservices or shell; using Ubuntu Server 18.04 (Bionic Beaver) or Ubuntu 19.10 (Eoan Ermine) or Ubuntu 18.10 (Cosmic Cuttlefish) I always do like these steps, and it worked always too:
Creating a microservice called p example "brain_microservice1.service" in my case:
$ nano /lib/systemd/system/brain_microservice1.service
Inside this new service that you are in:
[Unit]
Description=brain_microservice_1
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3.7 /root/scriptsPython/RUN_SERVICES/microservices /microservice_1.py -k start -DFOREGROUND
ExecStop=/usr/bin/python3.7 /root/scriptsPython/RUN_SERVICES/microservices/microservice_1.py -k graceful-stop
ExecReload=/usr/bin/python3.7 /root/scriptsPython/RUN_SERVICES/microservices/microservice_1.py -k graceful
PrivateTmp=true
LimitNOFILE=infinity
KillMode=mixed
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Give the permissions:
$ chmod -X /lib/systemd/system/brain_microservice*
$ chmod -R 775 /lib/systemd/system/brain_microservice*
Give the execution permission then:
$ systemctl daemon-reload
Enable then, this will make then always start on startup
$ systemctl enable brain_microservice1.service
Then you can test it;
$ sudo reboot now
Finish = SUCCESS!!
This can be done with the same body script to run shell, react ... database startup script ... any kind os code ... hope this help u...
...
For some people, this will work:
You could simply add the following command into System → Preferences → Startup Applications:
bash /full/path/to/your/script.sh

Resources