41

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?

Jurian Sluiman
  • 13,498
  • 3
  • 67
  • 99
  • 1
    Does it work if you add `nohup(1)`? `su www-data -c 'nohup node /var/www/php-jobs/manager.js >> /var/log/php-jobs.log 2>&1 &'` Or do you need to give an absolute path to `node` because it isn't in the `PATH` that is used during early boot? `su www-data -c '/path/to/node /var/www/php-jobs/manager.js >> /var/log/php-jobs.log 2>&1 &'` – sarnold Oct 16 '11 at 09:31
  • 1
    Unfortunately, that doesn't work either. I have tried a) add nohup b) add absolute path /usr/bin/node and c) checked permissions of /var/log/php-jobs.log, they are set to www-data:www-data. After reboot, there is no `node` process (which is the case if I start it myself) and /var/log/php-jobs.log is empty. Thanks for the quick reply, other suggestions? – Jurian Sluiman Oct 16 '11 at 09:56
  • 2
    Perhaps add an `upstart` configuration file instead; [apparently it needs `HOME` to be configured](http://kevin.vanzonneveld.net/techblog/article/run_nodejs_as_a_service_on_ubuntu_karmic/)? – sarnold Oct 16 '11 at 10:09
  • I've changed to upstart, which does a better job. Problem is solved now :) – Jurian Sluiman Oct 16 '11 at 13:44
  • @JurianSluiman: perhaps answer your own question, sharing the upstart script so others can learn from your experience? – sehe Oct 16 '11 at 20:01
  • @sehe Will write an answer. With upstart I found another problem, solving that now and will finally post a complete solution. – Jurian Sluiman Oct 16 '11 at 20:11

18 Answers18

73

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
John Doe
  • 2,746
  • 2
  • 35
  • 50
  • This didn't work. On startup, the log file wasn't created (but it was created when I ran the script manually). – Donald Duck Mar 16 '18 at 09:24
  • debug facility worked very well in my case, thanks for the hint! id it doesn't work, make sure the `/tmp` directory exists and is writable (which should be the case in most normal circumstances). – Remigius Stalder Apr 30 '19 at 08:55
12

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.

Rahil Wazir
  • 10,007
  • 11
  • 42
  • 64
user3533658
  • 189
  • 2
  • 2
  • This solved my problem. I had redirected `/etc/rc.local` to my own config file with a symlink. It worked fine when I ran it, but `/etc/rc.local` was not accessed on boot. I replaced `/etc/rc.d/rc.local` with a symlink to my config file and then reinstituted the default CentOS `/etc/rc.local` symlink to `/etc/rc.d/rc.local`. – T. Brian Jones Oct 09 '14 at 20:51
5

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.

Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
Boyan
  • 67
  • 1
  • 1
5

I ended up with upstart, which works fine.

Jurian Sluiman
  • 13,498
  • 3
  • 67
  • 99
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes (and in this case, the link is broken so your answer is invalid). – Donald Duck Mar 16 '18 at 09:25
  • The link doesn't work. As per http://upstart.ubuntu.com/: "Project is in maintaince mode only. No new features are being developed and the general advice would be to move over to another minimal init system or systemd." – Remigius Stalder Apr 30 '19 at 09:01
4

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 &.

w00t
  • 17,944
  • 8
  • 54
  • 62
3

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

chmod +x /etc/rc.local
Gayolomao
  • 586
  • 4
  • 15
2

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).

Pawel
  • 407
  • 1
  • 6
  • 14
superyuan
  • 21
  • 2
1

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.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
CatGuyTX
  • 11
  • 2
  • I put my script.sh in /etc/init.d, but its not executing at boot. could you tell me what to do edit in /etc/rc.local to work my scirpt.sh – Mohini Aug 12 '15 at 13:56
1

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.

lppier
  • 1,927
  • 3
  • 24
  • 62
  • The problem with this approach is that these scripts are executed at login, rather than startup. They'll execute every time somebody logs in, and as that user, so for instance anything that requires `root` won't work. – robert Jan 14 '16 at 09:05
1

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
Heapify
  • 2,581
  • 17
  • 17
0

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.

Asad R.
  • 1,051
  • 13
  • 20
0

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.

RVQ
  • 1
0

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..

Nikhil Parashar
  • 431
  • 5
  • 11
0

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.

Jachdich
  • 782
  • 8
  • 23
0

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.

0

Have you verified you have systemd package installed? It's not default in all ubuntu versions.

sudo apt-get install systemd
sudo systemctl status rc-local
sudo systemctl enable rc-local

and a reminder to everyone else, first line #!/bin/sh -e and last line exit 0

Antti Rytsölä
  • 1,485
  • 14
  • 24
-1

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...

fantaxy025025
  • 809
  • 8
  • 7
-3

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.

Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
Jason
  • 1