Monday, 23 March 2009

How to run an application a daemon? Example with nsca Nagios utility

Recently I needed to make a server application run as an Unix daemon and be able to start, stop and restart it on demand. The application I’m talking about didn’t have any startup/shutdown utilities (nsca utility to send passive check results to Nagios). It runs as a script, without even detaching from the console ( unless you use the & at the end of the command line, let's say #nsca -c nsca.cfg & ).
I also did it some time ago, to make another utility work as a daemon, but today I want to share the info.
I’ll have to write a utility application that would start the process, store it’s PID in some file and somehow “daemonize” the forked process.

Let’s assume that the application we want to run is /usr/local/nagios/nsca

First, we need to create a script in /etc/init.d/ Let us name the file /etc/init.d/nsca

The file contents would look something like this:

# /etc/rc.d/init.d/nsca
# Control to start/stop nsca utility as a daemon
# chkconfig: 345 99 01
# description: NSCA passive alerts writer for Nagios
# Author: Edwin Salvador (
# Changelog:
# 2009-03-23
# - First version of the script
# processname: nsca
# Source function library.
. /etc/init.d/functions

test -x /usr/local/nagios/nsca || exit 0


prog="NSCA passive alerts writer for Nagios"

start() {
echo -n $"Starting $prog: "
daemon /usr/local/nagios/nsca -c /usr/local/nagios/nsca.cfg
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/nsca

stop() {
echo -n $"Stopping $prog: "
killproc /usr/local/nagios/nsca
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/nsca

# See how we were called.
case "$1" in
if [ -f /var/lock/subsys/nsca ]; then
status /usr/local/nagios/nsca
echo $"Usage: $0 {condrestart|start|stop|restart|reload|status}"
exit 1

exit $RETVAL

This is a pretty standard service start/stop/restart file. This small script will take care of controlling the PID and work as any other standard service, you don't need to remove any PID file manually, nor event to kill the process.

It can also be easyly modified to match any other program / application / script under Linux you want to daemonize !!.

Remember to assign user and group "root", and chmod 755
Use a different and unique name to each new startup script you create.

You're all set. Just use it as any usual service you run:

#service start nsca
#service stop nsca
#service restart nsca

If you need it to startup automatically on system boot-up:

#chkconfig nsca on

Enjoy it !

Thursday, 12 March 2009

Sudo: allow a normal user to run commands as root under Linux / UNIX operating systems

I would like to run few commands such as stop or start web server as a root user. How do I allow a normal user to run these commands as root?

You need to use sudo command which is use to execute a command as another user. It allows a permitted user to execute a command as the superuser or another user, as specified in the /etc/sudoers (config that defines or list of who can run what) file. i.e. the sudo command allows users to do tasks on a Linux system as another user.

sudo is more more secure then su command. By default it logs sudo usage, command and arguments in /var/log/secure (Red Hat/Fedora / CentOS Linux) or /var/log/auth.log (Ubuntu / Debian Linux).

If the invoking user is root or if the target user is the same as the invoking user, no password is required. Otherwise, sudo requires that users authenticate themselves with a password by default (NOTE: in the default configuration this is the user's password, not the root password). Once a user has been authenticated, a timestamp is updated and the user may then use sudo without a password for a short period of time (15 minutes unless overridden in sudoers).

/etc/sudoers Syntax
Following is general syntax used by /etc/sudoers file:

USER: Name of normal user
HOSTNAME: Where command is allowed to run. It is the hostname of the system where this rule applies. sudo is designed so you can use one sudoers file on all of your systems. This space allows you to set per-host rules.
COMMAND: A simple filename allows the user to run the command with any arguments he/she wishes. However, you may also specify command line arguments (including wildcards). Alternately, you can specify "" to indicate that the command may only be run without command line arguments.
How do I use sudo?
For example, you want to give user rokcy access to halt/shutdown command and restart apache web server.
1) Login as root user

2) Use visudo command edit to edit the config file:
# visudo
3) Append the following lines to file:
rokcy localhost=/sbin/halt
rokcy dbserver=/etc/init.d/apache-perl restart
4) Save the file and exit to shell prompt.
5) Now rokcy user can restart apache server by typing the following command:
$ sudo /etc/init.d/apache-perl restart

Restarting apache-perl 1.3 web server....The sudo command has logged the attempt to the log file /var/log/secure or /var/log/auth.log file:
# tail -f /var/log/auth.log


May 13 08:37:43 debian sudo: rokcy : TTY=pts/4 ; PWD=/home/rokcy ; USER=root

If rokcy want to shutdown computer he needs to type command:
$ sudo /sbin/halt

Password:Before running a command with sudo, users usually supply their password. Once authenticated, and if the /etc/sudoers configuration file permits the user access, then the command is run. sudo logs each command run and in some cases has completely supplanted the superuser login for administrative tasks.

More examples
a) Specify multiple commands for user jadmin:
jadmin ALL=/sbin/halt, /bin/kill, /etc/init.d/httpd
b) Allow user jadmin to run /sbin/halt without any password i.e. as root without authenticating himself:
jadmin ALL= NOPASSWD: /sbin/halt
c) Allow user charvi to run any command from /usr/bin directory on the system devl02:
charvi devl02 = /usr/bin/*


HowTo SSH/SCP without a password

HowTo SSH/SCP without a password.

This small HowTo will explain how to setup key-based authentication for password-less SSH and SCP usage.

This HowTo does assume the reader has some basic knowledge of ssh and a terminal, and is using an operating system that implements SSH. If you're using a Windows OS and want to use SSH, try PuTTY. For Putty, see key-based auth with Putty.

In the examples that follow please substitute 'servername' , 'ipaddress' and 'username' with the proper information for your setup. I have included a list of weblinks for the words in italic at the end of this document.

Step 1. Verify that you can connect normally (using a password) to the server you intend to setup keys for:

#### Examples ####

user@homebox ~ $ ssh username@'servername'

# Or:

user@homebox ~ $ ssh username@'ipaddress'

# If your username is the same on both the client ('homebox') and the server ('servername'):

user@homebox ~ $ ssh 'servername'

# Or:

user@homebox ~ $ ssh 'ipaddress'

# If this is your first time connecting to 'servername' (or 'ipaddress'), upon establishing a connection with the
# server you'll be asked if you want to add the servers fingerprint to the known_hosts file on your computer.
# Press 'enter' to add the fingerprint.

Step 2. Now that you're connected to the server and verified that you have everything you need for access (hopefully), disconnect by typing 'exit' .

#### Examples ####

user@servername ~ $ exit

# You should be back at:

user@homebox ~ $

Step 3. The next step is to copy a unique key generated on your 'homebox' to the server you are connecting too. First, before you generate a new key, check to see if you already have a key:

#### Example ####

user@homebox ~ $ ls -l ~/.ssh
total 20
-rwx--xr-x 1 user user 601 Feb 2 01:58 authorized_keys
-rwx--xr-x 1 user user 668 Jan 1 19:26 id_dsa
-rwx--xr-x 1 user user 599 Jan 1 19:26
-rwx--xr-x 1 user user 6257 Feb 2 21:04 known_hosts

# The file we need to copy to the server is named As you can see above, the file needed exists. You may or may not have other files in ~/.ssh as I do. If the key doesn't exist, however, you can make one as follows:

#### Example ####

user@homebox ~ $ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_dsa): # Press 'enter' here
Enter passphrase (empty for no passphrase): # Press 'enter' here
Enter same passphrase again: # Press 'enter' here
Your identification has been saved in /home/user/.ssh/id_dsa.
Your public key has been saved in /home/user/.ssh/
The key fingerprint is:
6f:c3:cb:50:e6:e9:90:f0:0f:68:d2:10:56:eb:1d:91 user@host

# Entering a password when asked during the key generation processes when prompted would require you to enter a password each time you SSH/SCP to the server which defeats the purpose of this document.

Step 4. Regardless whether you had a key ready to go or if you had to generate a new key, the next step is the same in either case. Now you're ready to copy the key to the server. Do so like this:

#### Example ####

user@homebox ~ $ ssh-copy-id -i ~/.ssh/ user@'servername' (or 'ipaddress')

# If you are asked weather or not you wish to continue, say yes.

Step 5. Now it's time to test the setup. To do that, try to ssh to the server:

#### Example ####

user@homebox ~ $ ssh 'servername' (or 'ipaddress')

# You should log in to the remote host without being asked for a password.

Step 6. You can now SSH or SCP to the remote host without having to enter a password at each connection. To make sure your public key stays secure from prying eyes, do the following to change permissions and restrict access on 'homebox' and also on 'servername' to ~/.ssh:

#### Example ####

user@homebox ~ $ chmod 600 ~/.ssh/id_dsa ~/.ssh/

# Verify the permissions on the files:

#### Example ####

user@homebox ~ $ ls -l ~/.ssh
-rw------- 1 user user 668 Feb 4 19:26 id_dsa
-rw------- 1 user user 599 Feb 4 19:26


1. OpenSSH

2. known_hosts

3. fingerprint

Nice post!

I've noticed that I don't have the command ssh-copy-id on my OS X machine (I didn't even know one existed!). To achieve the same effect I usually do the following:
user@homebox ~ $ scp ~/.ssh/ user@'servername':.ssh/authorized_keysThis is assuming you've already created a .ssh directory on your server 'servername' (just ssh in as normal and `mkdir .ssh`). This also assumes that you don't already have an `authorized_keys` file in the .ssh directory on your server. If you do just copy (scp) the file to a temporary file in your server's home directory and then
user@homebox ~ $ scp .ssh/ user@servername:homebox_dsa.pubuser@homebox ~ $ ssh user@servernameuser@servername ~ $ cat >> .ssh/authorized_keysuser@servername ~ $ rm If you've got it, the ssh-copy-id way is clearly a lot easier!

~ Mark

Hi Mark. Thanks for adding that bit. I don't have access to a Mac (new one anyway) so that's very nice to know.


Seth, I liked this post a lot, but felt the formatting and wording can be improved. I've made a few changes to the introduction.

(I wish I had used my name for my username now!)


I found an elegant way of creating a new, or adding to an existing authorized_keys file with a single command:

ssh -n "echo `cat ~/.ssh/` >> ~/.ssh/authorized_keys"-

I think it *is* a good practice to use pass phrases when using ssh keys. You can use ssh-agent on Linux and SSH Agent or SSHKeychain on Mac OS X, to avoid you to type your pass phrase everytime you access a remote host. Also, you can forward your keys using 'ssh -A' if you need to hop onto some host in the middle.

-- Igor