Users trying to run a script as a daemon on a modern system should be using systemd:

[Unit]
Description=hit service
After=network-online.target

[Service]
ExecStart=/path/to/hit.sh

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/hit.service, and then you will be able to start/stop/enable/disable it with systemctl start hit, etc.

Old answer from 2015:

If you'd like to reuse your code sample, it could look something like:

#!/bin/bash

case "$1" in 
start)
   /path/to/hit.sh &
   echo $!>/var/run/hit.pid
   ;;
stop)
   kill `cat /var/run/hit.pid`
   rm /var/run/hit.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/hit.pid ]; then
      echo hit.sh is running, pid=`cat /var/run/hit.pid`
   else
      echo hit.sh is NOT running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0 

Naturally, the script you want to be executed as a service should go to e.g. /usr/local/bin/hit.sh, and the above code should go to /etc/init.d/hitservice.

For each runlevel which needs this service running, you will need to create a respective symlink. For example, a symlink named /etc/init.d/rc5.d/S99hitservice will start the service for runlevel 5. Of course, you can still start and stop it manually via service hitservice start/service hitservice stop

Answer from Dmitry Grigoryev on Stack Exchange
Top answer
1 of 6
59

Users trying to run a script as a daemon on a modern system should be using systemd:

[Unit]
Description=hit service
After=network-online.target

[Service]
ExecStart=/path/to/hit.sh

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/hit.service, and then you will be able to start/stop/enable/disable it with systemctl start hit, etc.

Old answer from 2015:

If you'd like to reuse your code sample, it could look something like:

#!/bin/bash

case "$1" in 
start)
   /path/to/hit.sh &
   echo $!>/var/run/hit.pid
   ;;
stop)
   kill `cat /var/run/hit.pid`
   rm /var/run/hit.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/hit.pid ]; then
      echo hit.sh is running, pid=`cat /var/run/hit.pid`
   else
      echo hit.sh is NOT running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0 

Naturally, the script you want to be executed as a service should go to e.g. /usr/local/bin/hit.sh, and the above code should go to /etc/init.d/hitservice.

For each runlevel which needs this service running, you will need to create a respective symlink. For example, a symlink named /etc/init.d/rc5.d/S99hitservice will start the service for runlevel 5. Of course, you can still start and stop it manually via service hitservice start/service hitservice stop

2 of 6
39

I believe CentOS 7 and above uses systemd. If that is the case for your system, try the following:

  1. Place the script commands you wish to run in /usr/bin/myscript.

  2. Remember to make the script executable with chmod +x.

  3. Create the following file:

/etc/systemd/system/my.service

[Unit]
Description=My Script

[Service]
Type=forking
ExecStart=/usr/bin/myscript

[Install]
WantedBy=multi-user.target
  1. Reload all systemd service files: systemctl daemon-reload

  2. Check that it is working by starting the service with systemctl start my.

Bonus:

For testing the systemd service, it is possible to launch a tmux environment with two window panes, where the top window monitors the output from the script (stdout and stderr) and the bottom window can be used for restarting services. This requires tmux to be installed, then simply:

tmux new-session \; select-layout even-horizontal \; split-window -v journalctl -o cat --since=@$(date +%s) -f -u my \; rotate-window \; set -g status-bg colour0 \; set -g status-fg colour9 \; attach

Then restart the service with:

systemctl restart my

Exit tmux with ctrl-d and then ctrl-c.

Once you're happy with the script and service file, change

Type=forking

into

Type=simple

Done.

🌐
TecAdmin
tecadmin.net › run-shell-script-as-systemd-service
How to Run Shell Script as Systemd in Linux – TecAdmin
April 26, 2025 - This always runs with PID 1. This ... on our Linux operating system. We can also run any custom script as systemd service. It helps the script to start on system boot. This can be helpful for you to run any script which required to run at boot time only or to run always. In our previous tutorial we have provides you instructions to run a Python script using Systemd. This tutorial covers running a shell script as ...
Discussions

I made a .service file to run a shell script, but it doesn't work
While you can make this a "user unit" as another user suggests, I'd focus on making it work first. Then make it work right later. So, making it work, there are multiple issues with the unit file: ExecStart=bash /home/hananelroe/custom-scripts/start-sound/startup.sh & This won't work. The trailing & is a shell construct, meaning that this command would have to be executed from a shell. However systemd does not use a shell to execute things. Also I don't know what distro & version you're using, but older versions of systemd required the absolute path to the executable (meaning you'd need ExecStart=/bin/bash ...). Also also, the use of the & implies that this is a long running command. If so, you shouldn't be trying to background it. Thats what systemd is for, tracking long running commands. Remove the & and change your Type=oneshot to Type=exec. ExecStart=bash PID=$! This won't work as you expect. Systemd units aren't scripting languages. Nor can you just pass script statements to bash as arguments like that. But with the above Type=exec change, this doesn't matter. Just delete this line. ExecStop=bash kill $PID This also won't work as expected. Same reasons as the above line. It's also unnecessary because systemd already handles process termination. Just let it do its job. Delete the line. OUTPUT=$(timeout .5 dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'") # timeout .5 terminates the command after .5 second This command requires being run with a dbus session. Commands executed by systemd are not associated with dbus sessions or X sessions. Your system can have multiple sessions running. How is systemd supposed to know which one it should use? Now if you did use a user unit there are ways you could inject the session variables into systemd, but that's probably not the route you should be taking here. Since this script is obviously related to a dbus & X session, you should be launching it from within that session. Most desktop environments have a way of launching commands on start. That's what you should likely be doing here. More on reddit.com
🌐 r/linux4noobs
3
4
July 5, 2022
Run Shell Script as SystemD Service in Linux - Unix & Linux Stack Exchange
To troubleshoot, run your script like this to simulate the conditions when executed by systemd: ... You should probably use full pathnames for every file you reference in your script, or explicitly include a cd /full/path/to/some/directory in the beginning of the script to ensure that relative path names are interpreted the way you expect. ... Find the answer to your question by asking... More on unix.stackexchange.com
🌐 unix.stackexchange.com
May 24, 2022
Run a sh file when starting a service (systemd or PM2)
I don't know PM2 but with systemd you'd use [Unit] After=a.service Bindsto=a.service [Service] ExecStart=/the/shell/file.sh [Install] WantedBy=a.service https://www.freedesktop.org/software/systemd/man/systemd.unit.html More on reddit.com
🌐 r/linuxquestions
2
1
April 7, 2022
debian - Run Bash Script as Service - Stack Overflow
Let me preface this my saying I am a Linux noob, so apologies for anything that should be painfully obvious but i'm not getting it. I have a phone server running on Debian, this phone server is supposed to send out emails when services crash, but this isn't always reliable, sometimes the services ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Power Sysadmin Blog
poweradm.com › home › running bash shell script as systemd service on linux
Running Bash Shell Script as Systemd Service on Linux - Power Sysadmin Blog
August 24, 2023 - On Linux, you can run a bash script as a service via systemd (instead of using the cron scheduler). This allows you to ensure that the script is always running, run the bash script on startup, check its health, and take advantage of other systemd ...
🌐
LinuxWays
linuxways.net › centos › how-to-run-shell-script-as-systemd-service-in-linux
How to Run Shell Script as Systemd Service in Linux – LinuxWays
Now, let’s make a service for running the script. Just create a file in the following directory. Note you can give any name but it must end with .service extension. ... [Unit] Description=My disk monitoring service Documentation=https://www.kernel.org/ #After=networking.service [Service] Type=simple User=root Group=root TimeoutStartSec=0 Restart=on-failure RestartSec=30s #ExecStartPre= ExecStart=/usr/bin/script.sh SyslogIdentifier=Diskutilization #ExecStop= [Install] WantedBy=multi-user.target
🌐
FOA(Fun Oracle Apps)
funoracleapps.com › home › run a shell script as systemd service in linux
Run a Shell Script as Systemd Service in Linux
February 26, 2022 - This also helps use to manage system and application service on our Linux operating system. We can also run any custom script as systemd service. It helps the script to start on system boot. This can be helpful for you to run any script which required to run at boot time only or to run always · 1) Create a script to monitor file system space · $ sudo vi /usr/bin/filesystem_check.sh ·
🌐
Medium
abhinand05.medium.com › run-any-executable-as-systemd-service-in-linux-21298674f66f
Run any Executable as Systemd Service in Linux | by Abhinand | Medium
November 7, 2020 - If you’re not using a venv, just execute the command below, otherwise activate the venv and then execute the command below, add the output as PYTHON_PATH in the shell script. ... Do not forget to give executable permission for the script, otherwise, this will not work. ... Now save this shell script and move it to /usr/sbin the directory. Why there? Because that is where we should put the general system-wide binaries that need admin privileges to run. ... The rest of the procedure is exactly the same. If you have succeeded in creating the service you should get a status like this.
🌐
Linuxapt
linuxapt.com › home › run shell script as systemd service in linux
Run Shell Script as Systemd Service in Linux
January 2, 2024 - This always runs with pid 1. This ... start on system boot, also start the service using the following commands:$ sudo systemctl enable shellscript.service $ sudo systemctl start shellscript.service 3. To verify the script is ...
Find elsewhere
🌐
Reddit
reddit.com › r/linux4noobs › i made a .service file to run a shell script, but it doesn't work
r/linux4noobs on Reddit: I made a .service file to run a shell script, but it doesn't work
July 5, 2022 -

the startup-scripts.service file:

(it's named like that because I might add more bash scripts to it later)

[Unit]
Description=starts a startup sound script

[Service]
Type=oneshot
WorkingDirectory=/home/hananelroe/custom-scripts/start-sound
ExecStart=bash /home/hananelroe/custom-scripts/start-sound/startup.sh & 
ExecStart=bash PID=$!
ExecStop=bash kill $PID

[Install]
WantedBy=multi-user.target

the .sh file:

#!/bin/bash

while true
do
	OUTPUT=$(timeout .5 dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'") # timeout .5 terminates the command after .5 second
	
	if echo "$OUTPUT" | grep -q "member=WakeUpScreen"; then
    	echo "playing starup sound..."
    	mpg123 ./sound.mp3 > /dev/null 2>&1
	fi
done

the .sh script does work if I activate it manually.

to use the service I type:

sudo systemctl daemon-reload
sudo service startup-scripts start

startup-scripts.service is located at /usr/lib/systemd/system/

Top answer
1 of 2
2
While you can make this a "user unit" as another user suggests, I'd focus on making it work first. Then make it work right later. So, making it work, there are multiple issues with the unit file: ExecStart=bash /home/hananelroe/custom-scripts/start-sound/startup.sh & This won't work. The trailing & is a shell construct, meaning that this command would have to be executed from a shell. However systemd does not use a shell to execute things. Also I don't know what distro & version you're using, but older versions of systemd required the absolute path to the executable (meaning you'd need ExecStart=/bin/bash ...). Also also, the use of the & implies that this is a long running command. If so, you shouldn't be trying to background it. Thats what systemd is for, tracking long running commands. Remove the & and change your Type=oneshot to Type=exec. ExecStart=bash PID=$! This won't work as you expect. Systemd units aren't scripting languages. Nor can you just pass script statements to bash as arguments like that. But with the above Type=exec change, this doesn't matter. Just delete this line. ExecStop=bash kill $PID This also won't work as expected. Same reasons as the above line. It's also unnecessary because systemd already handles process termination. Just let it do its job. Delete the line. OUTPUT=$(timeout .5 dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'") # timeout .5 terminates the command after .5 second This command requires being run with a dbus session. Commands executed by systemd are not associated with dbus sessions or X sessions. Your system can have multiple sessions running. How is systemd supposed to know which one it should use? Now if you did use a user unit there are ways you could inject the session variables into systemd, but that's probably not the route you should be taking here. Since this script is obviously related to a dbus & X session, you should be launching it from within that session. Most desktop environments have a way of launching commands on start. That's what you should likely be doing here.
2 of 2
1
ExecStart=bash /home/hananelroe/custom-scripts/start-sound/startup.sh & A few things. One, don't use the script path as an argument to Bash, instead use a shebang line in the script. Example: #!/usr/bin/env bash Then invoke the script directly (it must have its execute bit set). Two, don't try putting the process in the background with '&', systemd does that for you and will get scrambled by this instruction. Three, go through your script and insert full paths for all commands. 'timeout' becomes /usr/bin/timeout, grep becomes /usr/bin/grep, mpg123 becomes a full path (I don't have this installed), and so forth.
🌐
LinuxConfig
linuxconfig.org › home › how to automatically execute shell script at startup boot on systemd linux
How to automatically execute shell script at startup boot on systemd Linux
September 22, 2025 - Store the scrip as /usr/local/bin/disk-space-check.sh. #!/bin/bash echo "Checking disk space on /home directory:" date > /root/disk_space_report.txt du -sh /home/ >> /root/disk_space_report.txt · This script writes the current date to a file and appends the disk space usage of the /home directory to it. Set Permissions and Enable Service: Set the necessary permissions and enable the systemd service to run at boot.
🌐
Medium
medium.com › geekculture › how-to-run-a-script-as-a-service-in-linux-4fb92cab6818
How to Run a Script as a Service in Linux | by Yann Mulonda | Geek Culture | Medium
November 8, 2022 - rc3. d is used for runlevel 3. All these directories contain executable scripts which have to be started at boot-up of Linux OS. As you see all the scripts are nothing but a soft link pointing to their original scripts in some other directory · Now, you can start, restart, stop, and check the status or log of your NodeJS app as a service by running the two following commands:
🌐
Reddit
reddit.com › r/linuxquestions › run a sh file when starting a service (systemd or pm2)
r/linuxquestions on Reddit: Run a sh file when starting a service (systemd or PM2)
April 7, 2022 -

Hello

I need help please to finish something. (I use Debian 11).

I'm looking for a solution so that an sh file I created, automatically runs when a service (which I also created myself) has finished restarting.

My service is a service that runs a Node.js App. Here it is (with PM2):

module.exports = {
  apps: [
    {
      name: "nextjs_mon-site-prod_1",
      cwd: "/home/steph/www/mon-site.com/prod/front-nextjs_1",
      script: "npm run start_prod_1", // and then I want to run an sh script
    },
  ],
};

I prefer to do this with PM2 (although I'm open to solutions with systemd).

Thanks in advance.

🌐
nixCraft
cyberciti.biz › nixcraft › howto › bash shell › how to run the .sh file shell script in linux / unix
How to run .sh file shell script (bash/ksh) in Linux / UNIX - nixCraft
July 17, 2024 - For example, if your script name is /home/nixcraft/job.sh, and wish to run the same in the background, type $ /home/nixcraft/job.sh & You can also try the nohup command or disown command as follows when you wish to close the terminal, but the script must be running in the background like a service: $ nohup /home/nixcraft/job.sh & $ exit ## OR ## $ /home/nixcraft/job.sh & $ disown %1 $ exit See “nohup Execute Commands After You Exit From a Shell Prompt” for more info.
🌐
Stack Overflow
stackoverflow.com › questions › 66754261 › run-bash-script-as-service
debian - Run Bash Script as Service - Stack Overflow
So it should be obvious that it's looking in the wrong directory. ... The bash script is running in the same directory as the mail.txt so I didn't specify the full path, is the full path still required if its in the same directory? ... Regarding the question about how its going to detect a problem, the idea is to use the onfailure parameter in the services that are running and have it run this service when the service fails.
Top answer
1 of 3
277

Your .service file should look like this:

[Unit]
Description=Spark service

[Service]
ExecStart=/path/to/spark/sbin/start-all.sh

[Install]
WantedBy=multi-user.target

Now, take a few more steps to enable and use the .service file:

  1. Place it in /etc/systemd/system folder with a name like myfirst.service.

  2. Make sure that your script is executable with:

     chmod u+x /path/to/spark/sbin/start-all.sh
    
  3. Start it:

     sudo systemctl start myfirst
    
  4. Enable it to run at boot:

     sudo systemctl enable myfirst
    
  5. Stop it:

     sudo systemctl stop myfirst
    

Notes

  1. You don't need to launch Spark with sudo in your service, as the default service user is already root.

  2. Look at the links below for more systemd options.

Moreover

Now what we have above is just rudimentary, here is a complete setup for spark:

[Unit]
Description=Apache Spark Master and Slave Servers
After=network.target
After=systemd-user-sessions.service
After=network-online.target
 
[Service]
User=spark
Type=forking
ExecStart=/opt/spark-1.6.1-bin-hadoop2.6/sbin/start-all.sh
ExecStop=/opt/spark-1.6.1-bin-hadoop2.6/sbin/stop-all.sh
TimeoutSec=30
Restart=on-failure
RestartSec=30
StartLimitInterval=350
StartLimitBurst=10
 
[Install]
WantedBy=multi-user.target

To setup the service:

sudo systemctl start spark.service
sudo systemctl stop spark.service
sudo systemctl enable spark.service

Further reading

Please read through the following links. Spark is a complex setup, so you should understand how it integrates with Ubuntu's init service.

  • https://datasciencenovice.wordpress.com/2016/11/30/spark-stand-alone-cluster-as-a-systemd-service-ubuntu-16-04centos-7/
  • https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
  • https://www.freedesktop.org/software/systemd/man/systemd.unit.html
2 of 3
7

Copy-paste this into a terminal (as root) to create /root/boot.sh and run it on boot:

bootscript=/root/boot.sh
servicename=customboot

cat > $bootscript <<EOF
#!/usr/bin/env bash
echo "$bootscript ran at \$(date)!" > /tmp/it-works
EOF

chmod +x $bootscript

cat > /etc/systemd/system/$servicename.service <<EOF
[Service]
ExecStart=$bootscript
[Install]
WantedBy=default.target
EOF

systemctl enable $servicename

To modify the parameters, for example to use a different $bootscript, just set that variable manually and skip that line when copying the commands.

After running the commands, you can edit /root/boot.sh using your favorite editor, and it will run on next boot. You can also immediately run it by using:

systemctl start $servicename
🌐
SUSE
suse.com › support › kb › doc
Create a simple systemd service unit file and run a script on boot | SUSE | Support Center
With SUSE Linux Enterprise Server 12 and above, a systemd service unit file is needed. There are MANY parameters you can add, but here is the most simple version of a unit file: ... Here is a very simple script to run. For this basic setup we create a simple script that runs once and then is done as part of the boot process. For this example the script is in /usr/sbin/. The script needs to be marked executable. server1:/root/ # ls -lah /usr/sbin/example.sh -rwxr-xr-x 1 root root 58 Jul 24 14:14 /usr/sbin/example.sh server1:/root/ # cat /usr/sbin/example.sh #!/bin/bash echo "the script works" >> /tmp/diditwork.txt Next create a systemd service unit file named test.service.
🌐
Infotopics
docs.infotopics.com › enterprise-installation › installation-guide › getting-started › linux › run-as-a-service-on-linux
Run as a service on Linux | Enterprise Installation | Documentation
November 19, 2025 - [Unit] Description=Extension Name Service After=network.target [Service] User=root WorkingDirectory=/usr/local/bin # when using config: # ExecStart=/usr/local/bin/super-tables-linux # when NOT using config: # ExecStart=/usr/local/bin/super-tables-linux –-port 443 –-cert yourdomain.crt –-key yourdomain.key Restart=always [Install] WantedBy=multi-user.target · This defines a simple service. The critical part is the ExecStart directive, which specifies the command that will be run to start the service.