In my linux startup scripts, when I start a process like (openvpn used for this example, but the question is general to any process);
openvpn --config /etc/myserver.conf
what is the best way to find it and be 100% certain it's the right process and kill it in the stop section? I normally use stuff like:
pid=$(ps -efww | grep -v grep | grep openvpn | grep /etc/myserver.conf | awk '{print $2}')
Sure it works nearly all of the time, but sometimes there are issues with accidentally matching processes with nearly the same name (e.g. myserver.conf-new), so I'm looking for a better approach.
- Some processes have a way to store the pid somewhere, that's fine, but generally I'm skeptical of killing processes solely based on a pid sitting in a file somewhere.
- Solaris has projects, it's not all roses in my limited experience because you have to set up /etc/projects first, but it does make it easy to tag and later find processes.
- Maybe using the environment, like setting an environment variable like (MYID=myserver) and then looking for it with
ps e -ef | grep MYID=myserver
? Still may suffer the same problem with accidental matching.
I wish there were something easy like:
launch --tag myserver openvpn --config /etc/myserver.conf
and
pgrep --tag myserver
Thank you @Iain, @KyleSmith, and @M_1 for your answers, and for helping me get started on Server Fault. If I had more rep here I'd +1 you guys. (Edit: now I have rep, +1s all around).
I'm going to answer my own question because I've found something that does what I was looking for: a general solution that avoids imprecise pattern matching with ps, and doesn't use pid files. It's completely subjective that this would be the "best" way because there's obviously a long and successful history in unix of using pid files, however this was something I explicitly said I didn't like for various reasons, and those are: they can be tricky to create properly, different for every piece of software, done differently on every distro, can be stale/overwritten, and inherently don't necessarily represent what's actually going on. I'd rather use some kind of process tagging, ask the kernel and get real answers.
Trimmed down example:
The key points are:
I'm not sure I like polluting the environment, but I don't know of any other way (e.g. Solaris projects) to tag a linux process in an arbitrary way that I can ask the kernel for later. At least, /proc/<pid>/environ appears to reflect the environment at startup, and not be affected by any changes the process might make after, which suggests this should be reliable, however, there's the chance this could change unexpectedly. This may or may not work outside Linux, depending on the OS's /proc and grep implementation.
I think I'll give it a try for a while and see how it goes.
Don't be afraid of pidfiles, of they're tried and true and typically owned by root! :)
Most distributions use a standard function or binary to launch daemons and store the resultant PID in a file. In Debian, for example, you have start-stop-daemon with the
--pidfile
option. Other distributions have/etc/rc.d/init.d/functions
(or similiar) that are used for starting daemons. Check some of the more generic startup scripts included with your distribution.A nice idea would be to use a simple bash wrapper script that writes a lock/pid file of that application (commonly used in webservers or databases) and then use that file to kill exactly this one process if needed.
For openvpn in particular you can use the
--writepid /path/to/file
command line option e.g.Which will write the PID of the openvpn main process to the named file.
In general you can wrap your program in a small script and use the bash
$!
builtin variable to write the pid to a file