I'd like to have either a shell script or makefile to automate new user creation. I can't decide which of approach is better - a script or makefile?

I have two types or users - both are SFTP chrooted, individual account and a shared account for web domains.

New users "register" with an email address and I check DNS MX record if the domain is valid and RCPT if username is valid recipient.

Then I cannot use useradd -m as it would create homedir owned by the user, but for SFTP chroot it must be root owned and not writable by anybody else. Thus I create the dir and dir layout manually.

I can't also use userdel -r to remove such user completely, as userdel -r won't remove homedir if it is not owned by the user (at least on OpenBSD).

What's better for such task, a script or a makefile?

PS: I don't want to go with ansible etc...

  • I wrote both for now, they do the same. The Makefile is half of length of the ksh script :)
    – Jiri B
    Commented Jan 26, 2019 at 2:22

1 Answer 1


I strongly suggest to use a script and not a makefile.

The reasons are, in short:

  • adhering to common practice. or the principle of least astonishment.
  • maintainability and extensibility.
  • and the fact that makefiles are designed to automate a build process, not to automate sysadmin tasks.

It is not inherently "wrong" to use a makefile, it has it's benefits, but also a lot of caveats. Whatever you decide you should know the trade offs.

Let me elaborate.

adhering to common practice or the principle of least astonishment

When I see a script I assume it automates something. When I see a makefile I assume it builds something. When I work in your office and I want to add a user and I look in the documentation and it says to run a makefile I will be confused at first. Will the makefile build the tool that I then use to add a user? I will have to examine the makefile to make sure it really does add a user.

maintainability and extensibility

Change happens. Systems change. Requirements change. Tools will need to be adapted. Here are some caveats I can think of when trying to adapt a makefile that is used to automate a sysadmin task.

In no particular order:

  • You have to prepend every line in the recipe with a tab (see makefile rule syntax defintion). Maybe this is just my personal annoyance. It can be overcome with a good editor which can be configured to not replace the leading tab with spaces in makefiles. workaround possible with .RECIPEPREFIX but then you are again breaking common expectation.

  • You can't (easily) handle arguments in makefiles. This will make it very hard to add arguments like --verbose or --force or --no-action. See here for more explanation: https://stackoverflow.com/a/45003119/360899

  • In addition to above: you can't customize the argument handling error messages. In other words: you can't write meaningful error messages if the user gave incorrect arguments

  • You can't (easily) extract common code to functions. There are "canned recipes". But I'd rather not.

  • You can't (easily) write multiline shell script constructs because make executes every line in the recipe for itself. For example if [ condition ]; then commands; fi or for elements; do commands; done has to be written in one line. workaround possible using .ONESHELL

  • Also, because of the above, you can't (easily) set a flag in one line and act on the flag in a line further down. Because each line stands on its own. workaround as above.

  • Other arcane makefile quirks. For example:

Bonus problem: you can't put a makefile in /usr/bin or ~/bin. you will need to write a wrapper script anyway.

makefiles are designed to automate a build process, not to automate sysadmin tasks

Using makefiles to automate system tasks would be like using git, instead of rsync, for system backup.

Make is a powerful tool with a lot of quirks to automate build processes. Git is a powerful tool with a lot of quirks to do code versioning. The quirks are tolerable if using the tool is helping a lot. But if there are other tools better meant for the task at hand then why work around the quirks from a tool meant to do something else.

Some demonstration:

The benefit of a makefile, that i can think of, would be that you do not need to write boilerplate for argument handling. Compare:


    @echo commands that do the things for useradd

    @echo commands that do the things for userdel



if [ $# == 0 ]; then
  echo "need argument: useradd or userdel"
  exit 1

if [ "$1" == "useradd" ]; then
  echo "commands that do the things for useradd"
elif [ "$1" == "userdel" ]; then
  echo "commands that do the things for userdel"
  echo "unknown argument: $1"
  exit 1

But then:

$ make userdell
make: *** No rule to make target 'userdell'.  Stop.
$ ./script.sh userdell
unknown argument: userdell

you can't customize the error messages.

$ touch userdel
$ make userdel
make: 'userdel' is up to date.

if a file named userdel exists, for whatever reason, make will correctly deduce that there is nothing that needs to be done.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .