I have the following script:


echo "Merging pool...";

if !(mergerfs -o minfreespace=4G,defaults,allow_other,category.create=ff /media/pool/hdd1:/media/pool/hdd2:/media/pool/hdd4:/media/pool/hdd5 /media/pool/merged/)
        echo "Merging failed."
        exit 1;

echo "Done";

exit 0;

It is saved in /home/me/scripts/mergePool.sh. If I manually run the script like this: sudo ./mergePool.sh, it works fine

I made this unit in /etc/systemd/system/mergePool.service:

Description=Merge all pool drives into one big virtual drive

ExecStart=/bin/bash /home/me/scripts/mergePool.sh


If I run the unit like this:

sudo systemctl start mergePool.service

It produces no error and it doesn't work at all.

This is the log:

sudo systemctl status mergePool.service
● mergePool.service - Merge all pool drives into one big virtual drive
   Loaded: loaded (/etc/systemd/system/mergePool.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sat 2020-02-29 12:26:07 CET; 6min ago
  Process: 2066 ExecStart=/bin/bash /home/me/scripts/mergePool.sh (code=exited, status=0/SUCCESS)
 Main PID: 2066 (code=exited, status=0/SUCCESS)

Feb 29 12:26:07 junkbox systemd[1]: Starting Merge all pool drives into one big virtual drive...
Feb 29 12:26:07 junkbox bash[2066]: Merging pool...
Feb 29 12:26:07 junkbox bash[2066]: Done
Feb 29 12:26:07 junkbox systemd[1]: Started Merge all pool drives into one big virtual drive.

This is quite confusing to me, why doesn't it work when the script is ran by systemd?

  • Can you be more specific about what "doesn't work at all", exactly? Feb 29 '20 at 15:56
  • mergerfs should merge the specified partitions and mount them onto the merged dir, but this doesn't happen, the directory remains empty and and is not a mountpoint
    – Askerman
    Feb 29 '20 at 16:24

While I don't know why your script is failing, I do see a couple of things that should be fixed, which might get you closer to a solution even if they aren't the solution in and of themselves:

  • When launching an executable script that has a sha-bang specifying the appropriate shell/interpreter, as in your example, don't call /bin/bash explicitly when you want to run the script. Just call the script.
  • If and when you actually need to pass commands directly in a bash invokation, the syntax is /bin/bash -c "<commands to execute>". What your example is doing is first running /bin/bash with no arguments or commands, then (as a completely separate second command) running your script. In a oneshot type service that shouldn't actually break anything, but do keep in mind that oneshot is the only service type that allows more than one command in this way.
  • By wrapping a single command in a shell script in this context, all you really accomplish is making things opaque to systemd. Try simply putting your mergerfs command directly in the unit file's ExecStart= directive (you may need to enclose it in double quotes). That way systemd can capture mergerfs's exit status, and the journalctl log will contain any output and/or error messages produced by mergerfs. Then if it fails you should have some information as to why.

Note: For example, the .desktop files used for autostarting desktop goodies only accept one command. If you want to, say, autostart a program after a little delay, that one command could be /bin/bash -c "sleep 10; <program to launch>" It works because you're actually passing the double-quoted string of commands to bash as an argument, so the only command being run from the .desktop file is bash itself.


You should put the whole thing you want to run into an infinite loop without the exit code and a sleep 15 eg. to make the service ongoing.

  • Please expand your answer to give details on how to do this
    – Zanna
    Aug 6 '20 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.