make.
Make runs commands to create and/or transform files and uses the files' timestamps to determine if a command needs to be executed or can be skipped. For example:
foo:
$(info Creating foo ...)
touch foo
When you save the above in a file called Makefile
and run make foo
it will output "Creating foo ..."
and create an empty file foo
. When you call make foo
again make detects that foo
already exists and simply prints "'foo' is up to date"
without calling touch
again.
We can use this behavior to start a server and store its process ID (PID) in a file:
server.pid:
http-server . & echo $$! > $@
Let's break this down. http-server
is a simple web server that can be installed via npm (npm install -g http-server
). But you can use any other server implementation you like. The "&
" sends the server process into the background (i.e. it doesn't lock the console). "echo $$! > $@
" writes the PID ($$!
) to the file server.pid
($@
). Calling make server.pid
will start the server and create server.pid
just like the touch example above. It will also not start the server again if server.pid
is already present.
We can now create a make target that allows us to start our server with the command make start-server
:
start-server: server.pid
This simply means "The target 'start-server
' depends on the file server.pid
. So make sure it exists to complete this target."
Stopping the server is a bit more envolved:
stop-server:
test -f server.pid && kill `cat server.pid` && rm server.pid || true
"test -f
" tests if server.pid
is present and stops if it's not. "kill
" ends the process with the ID that's stored in server.pid
and "rm
" deletes the file. The last bit "|| true
" ensures that make returns without an error if server.pid
does not exist.
The entire Makefile looks like this:
.PHONY: start-server stop-server
start-server: server.pid
stop-server:
test -f server.pid && kill `cat server.pid` && rm server.pid || true
server.pid:
http-server . & echo $$! > $@
The .PHONY
bit tells make that start-server
and stop-server
are targets that (unlike server.pid
) do not correspond to files with those names.
Now you can start and stop your server like so:
$ make start-server
$ make stop-server
There is one caveat with this approach. In case you forget to make stop-server
before shutting down your machine you end up with a stale server.pid
file that you have to delete manually before you can start the server again.
Happy serving! ;-)