linux


Here a very simple init script tested on Suse SLES 10. An other good way to create one is looking at the init-Script for tomcat or using just it and installing Jira as WAR into tomcat.

#!/bin/bash
# Jira startup script
# install:
# copy to /etc/init.d/jirad
# ln -s /etc/init.d/jirad /sbin/rcmy-jirad
# insserv /etc/init.d/jirad
 
### BEGIN INIT INFO
# Provides:          jirad
# Required-Start:    $local_fs $network
# Required-Stop:
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: Starts Jira server
# Description:       Starts Jira Issue Tracking
### END INIT INFO
# Based on script at  http://confluence.atlassian.com/pages/viewpage.action?pageId=183148
 
RUN_AS_USER=jico
CATALINA_HOME=/opt/jira
 
start() {
        echo "Starting Jira: "
        if [ "x$USER" != "x$RUN_AS_USER" ]; then
          su - $RUN_AS_USER -c "$CATALINA_HOME/bin/startup.sh"
        else
          $CATALINA_HOME/bin/startup.sh
        fi
        echo "done."
}
stop() {
        echo "Shutting down Confluence: "
        if [ "x$USER" != "x$RUN_AS_USER" ]; then
          su - $RUN_AS_USER -c "$CATALINA_HOME/bin/shutdown.sh"
        else
          $CATALINA_HOME/bin/shutdown.sh
        fi
        echo "done."
}
 
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        sleep 10
        #echo "Hard killing any remaining threads.."
        #kill -9 `cat $CATALINA_HOME/work/catalina.pid`
        start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
esac
 
exit 0

Here is an init script to control hudson start up at boot time. It is tested on SLES 10 . I am not commenting it in detail here, nevertheless you are welcome to ask and leave comments. It’s rather beta but I hope that it could be useful as a starting point.

#!/bin/bash
# Author: Konstantin.rekk@gbv.de, 2008
# Using ideas from http://developer.novell.com/wiki/index.php/Writing_Init_Scripts
#
# install:
# copy to /etc/init.d/gbv-hudson-integration
# ln -s /etc/init.d/gbv-hudson-integration /sbin/rcgbv-hudson-integration
# insserv /etc/init.d/gbv-hudson-integration
 
 
### BEGIN INIT INFO
# Provides:          gbv-hudson-integration
# Required-Start:    $local_fs $network
# Required-Stop:
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: Starts the hudson server for CI 
# Description:       Starts Continuous Integration System for VZG SOA
### END INIT INFO
 
# to avoid conflict with functions local $1
ARG=$1
 
APP="hudson"
 
HUDSON_USER=soarun
HUDSON_GROUP=soarun
export HOME=/home/${HUDSON_USER}
export VZGSOA_HOME=${HOME}/soa-workarea
 
# include rc.status functions 
test -s /etc/rc.status && . /etc/rc.status && rc_reset
 
# use test_for_app <appl|file> (x|f)
test_for_app ()
{
    app_found=0
    if [ "f" = "$2" ] && [ -f $1 ]; then
        app_found=1
    elif [ "x" = "$2" ] && [ -x $1 ]; then
        app_found=1
    fi
    if [ 0 = $app_found ]; then
        echo -n "Warning:  Couldn't find $1"
        if [ "$ARG" = "stop" ] ; then
            rc_failed 0
        else
            rc_failed 5
        fi
        rc_status -v
        rc_exit
    fi
}
 
test_for_app $VZGSOA_HOME/vzgsoa.env f
test_for_app $VZGSOA_HOME/integration/integration.env f
. $VZGSOA_HOME/vzgsoa.env
. $VZGSOA_HOME/integration/integration.env
 
HUDSON_CMD="${JAVA} -jar ${HUDSON_WAR} --httpPort=${CI_HTTP_PORT} --argumentsRealm.passwd.hudson=${HUDSON_PW} --argumentsRealm.roles.hudson=admin"
 
HUDSON_PIDFILE=/var/run/hudson.pid
HUDSON_LOG=/var/log/hudson
 
usage ()
{
    echo ""
    echo "Usage: $0 <command> "
    echo ""
    echo "where <command> is one of the following:"
    echo "    start - start $APP if not running"
    echo "    stop - stop $APP if running"
    echo "    status - report whether $APP is running"
    echo "    restart - stop and restart $APP"
    echo "    usage, help - print this message"
}
 
get_pid_for_cmd ()
{
    for pid in `ls /proc`; do
        if [ -d /proc/$pid ] && [ -f /proc/$pid/cmdline ]; then
            if [ "$1" = "$(</proc/$pid/cmdline)" ]; then
		# return with current pid 
                return
            fi
        fi
    done
    pid=0
}
 
# checkport <port>
# returns port_used
check_port()
{
	port=$1
	if netstat -nlept 2>/dev/null | grep --regexp=":$port " &>/dev/null ; then
        	port_used=1
    	else
        	port_used=0
    	fi
}
 
# checks hudson, sets/returns status - 
# 0 if pidfile same as pid, running
# 3 no pidfile, not running (what with running?)
# 2 pidfile, but no process (remove file ...), not running
# 1 pidfile != pid, but running
# 4 no pidfile, but running
# 
# @todo: check port usage
check_hudson() 
{
	get_pid_for_cmd `eval echo ${HUDSON_CMD} | sed -e 's/ //g'`
 
	if [ -f $HUDSON_PIDFILE ]; then
		pidfile_pid=`cat $HUDSON_PIDFILE`
		if [ 0 = $pid ]; then
			status=2
		elif [ "$pid" = "$pidfile_pid" ]; then
			status=0;
		else 
			status=1;
		fi		
	else 
		if [ 0 = $pid ]; then
			status=3;
		else 
			status=4;
		fi
	fi
 
}
 
 
test_for_app ${JAVA} x
test_for_app ${HUDSON_WAR} f
 
case "$1" in
    start)
        check_hudson
        case "$status" in
            0)
                echo "${APP} already running"
		rc_failed 0
		rc_status -v1
           	rc_exit
                ;;
	    1|4)
		echo "${APP} seems running but pidfile is not up to date or doesn't exist, please check!"
		rc_failed
                rc_status -v1
                rc_exit
		;;
            2)
                echo "Found stale pidfile for ${APP} - unclean shutdown?"
                rm ${HUDSON_PIDFILE}
                ;;
            3)
                # not running - ok
        	check_port $CI_HTTP_PORT
		if [ $port_used = 1 ]; then
			echo "Port $CI_HTTP_PORT already in use, pleas check!"
                	rc_failed
                	rc_status -v1
                	rc_exit
		fi 
                ;;
            *)
                echo "Check for ${APP} failed"
                rc_failed
                rc_status -v1
                rc_exit
        esac
 
        echo -n "Starting ${APP}"
        startproc -f -u $HUDSON_USER -g $HUDSON_GROUP -p ${HUDSON_PIDFILE} ${HUDSON_CMD} >> ${HUDSON_LOG} 2>&1
        if ! [ 0 = $? ]; then
            echo -n "(Error - "
            case $? in
                2)
                    echo -n "invalid arguments"
                    ;;
                4)
                    echo -n "insufficient permission"
                    ;;
                5)
                    echo -n "no such program"
                    ;;
                7)
                    echo -n "launch failure"
                    ;;
                *)
                    echo -n "unspecified error"
                    ;;
            esac
            echo -n ")"
            rc_failed
            rc_status -v1
            rc_exit
        fi
	# removing spaces from commandline to be able to compare with /proc/<pid>/cmdline
        get_pid_for_cmd `eval echo ${HUDSON_CMD} | sed -e 's/ //g'`
        if [ 0 = $pid ]; then
            echo "Warning - Couldn't obtain PID for ${APP} "
        else
            echo $pid > ${HUDSON_PIDFILE}
        fi
        rc_status -v
        ;;
    stop)
        if [ $1 = "stop" ]; then
            check_hudson
	    if ! [ $status = 0 ]; then
		echo "Warning - not running!"
	    fi
            killproc -p ${HUDSON_PIDFILE} -t 10 ${JAVA}
            rc_status -v
        fi
        ;;
    status)
        check_hudson
	case "$status" in
        0)
            echo -n "(running)"
            rc_failed 0
            ;;
	1|4)  
	    echo -n "(running)"
	    echo -n  "Warning - PID corrupted"
            rc_failed 0
            ;;
        2)
            echo "(not running)"
            echo -n "Warning - PID file found"
            rc_failed 3
            ;;
        3)
            echo -n "(not running)"
            rc_failed 1
            ;;
        *)
            echo "(unknown)"
            echo "Warning - Couldn't get status"
            rc_failed 1
            rc_status -v1
            rc_exit
    esac
    rc_status -v
        ;;
    restart)
        $0 stop &>/dev/null
        $0 start &>/dev/null
        rc_status -v
        ;;
    usage|help)
        usage
        rc_exit
        ;;
    *)
        usage
        rc_failed 1
        rc_status -v
        rc_exit
esac

ls -d --sort=time */ | head -n 1

Since Version 1.1 subversion can deal with symlinks (see Does Subversion support symlinks?). There are only a few remarks in the manual Versioned Properties – svn:special and ‘svn add’ command.

Actually all handling of the symbolic link is up to the client. Cause in creation of symlinks the used paths do matter and subversion stores the link target in simple text file with the appropriate relative or absolute path you should choose the way you create your symlinks with care.

Example – Creating a symlink in your working copy:

$ mkdir A
$ ln -s A link
$ svn add --force .
A         A
A         link
$ svn commit -m "link there"

the contents of the link file in svn:
link A

Example – change symlink target

$ svn del --force link
$ svn commit -m "no link"
$ mkdir B
$ ln -s B link
$ svn add --force .
$ svn commit -m "link changed to B"

the contents of the link file in svn:
link B

To exclude certain files and directories from subversion’s version control you can set the ‘svn:ignore’ property as described in Ignoring Unversioned Items.
That works fine but nevertheless you might run into problems if you are using
svn add *
or similiar on linux systems. This is due to the shell expansion of wildcards. The above command is expanded to explicit files names svn add filename and seems to have the same effect as svn add --no-ignore filename.
Tip: Use svn add --force . instead!

Today I faced a strange bug caused by the interaction of the user-agent string of Firefox on ubuntu feisty and some paket filters. A site wouldn’t load with the error message above in Firefox, but it would load in Opera. Update of firefox package didn’t fix it.

Found this thread Connection Reset in Firefox but not other browsers and one proposed fix worked for me:

Open “about:config” , type useragent in filter and change setting “general.useragent.extra.firefoxComment” from (Ubuntu feisty) to (Ubuntu). The problem seems to be that substring “ist” is recognized as a malware signature by some paket filters.

Say you want to record a video live stream from the internet for example from the Streaming CCC Congress in Berlin 2007.

This can be accomplished using the glorious mplayer HOWTO Rip Streams With MPlayer.

To stop the recording after a certain amount of time use this simple script (see also my post Finding Child Process Pids … ):

#!/bin/bash
URL=$1
FILE=$2
# duration in minutes
DURATION=$3
mplayer -framedrop -autosync 30 -cache 10000 -dumpstream $URL -dumpfile $FILE &amp;amp;
sleep $DURATIONm
kill %+

Now you need to start this script at a certain time. For that you could use the linux “at” command (see at). To run it you have to export the DISPLAY variable on ubuntu (see Bug #94933):
export DISPLAY=$DISPLAY ; export TERM=$TERM; echo "echo 'Hallo'" | at  now

But I prefer KAlarm from KDE to schedule tasks which should run only once.
Run KAlarm, create New Alarm, choose Action “Command”, enter the path to your script with appropriate arguments for stream url, dumpfile and duration in minutes:
/home/myhome/scripts/stream_ripper.sh mms://streaming-internet.fem.tu-ilmenau.de/saal3 test.asf 60
, adjust all other settings which are quite self explaining. Use the template feature of KAlarm for similiar tasks.

To control background child processes from a shell script you want to know the PID or job-id of the child. Here are some ways to do this:

First starting a background process echoes the job-id and pid of the process:

$ emacs &amp;
[1] 15393

The PID of the last command set to run in the background by the current shell or script is stored in $! variable:
$ echo $!
15393

This you could find out by using the jobs command:
$ PID=`jobs -l | sed -n 's/^\[[0-9]*\] *+  *\([0-9]*\) .*$/\1/p'`; echo $PID
using the fact that the last current (last started) job will be marked by a + in
jobs -l output.
To terminate the current job you don’t need the explicit job-id:
$ kill %+
The exit status will be stored in the $? variable.
Read more in the Advanced Bash-Scripting Guide:Job Control Commands

I already wrote how to configure the ssh-client for single-sign-on in Convenient SSH on Linux. Today I would like to jump up to the KDE-Layer and see what there can be done to organize networking more effectively. Formerly I used kssh to organize my ssh-accounts (see Installing kssh on ubuntu). Nowadays I prefer a combination of KDE’s Network Folders and Terminal Sessions.

KDE Network Folders can help you to organize your remote access links. It is based on KDE’s support of webdav, ftp, sftp, smb and fish. Fish is quite interesting, it presents files over ssh just as they would be local. There is a special directory where your network folders are stored – type "remote:/" into Konqueror’s address bar. (Other possibility is of course to use simple bookmarks to organize remote connections accessed via “sftp://user@host/” or similiar.) It is just a collection of links which are stored in .kde/share/apps/remoteview by KDE.
The real value of Network Folders lies in the combination with Network Folder Wizard which gives you a configuration interface and quick access list in KDE’s panel.
Read the documentation of knetattach in Konqueror "help:/knetattach/introduction.html" which is the application behind Network Folders administration, also known as Network Folder Wizard also available as an applet by "RightClick Panel" -&gt;  "Add Applet to Panel" -&gt; "Network Folders".

Teminal Sessions is an other applet you can add to your panel. It will list the different konsole sessions. I use sessions to configure ssh shell access and to execute common shell commands like watching remote logs etc. . To add a session open a konsole window, in the menubar click "Settings" -&gt; "Configure Konsole" -&gt; "Session"-tab . In the “General” group type a name for your session, the command to execute (example: ssh xxx.gebewau.de) and your working directory, click save session. You can associate different color schema and icons with different sessions to have better orientation between konsole windows for different purposes. There seems to be no grouping feature for session links.

The Problem: There are a bunch of servers I need to login almost daily using ssh, all with different login names and passwords. I also want to secure copy data between them and access one server from another.

The Wish: One password for a group of servers to type in only once when I login into the local X-session.

A Solution: Set up passphrase protected private and public keys. Make ssh-agent run your window manager und type the keys passphrases into a pass-phrase dialog triggered by ssh-add on window managers startup. Use the ssh-agents forwarding features to forward local ssh-identities between remote hosts. Of course you
also need to configure your public key on the remote hosts.

So it goes:

  1. Install x11-ssh-askpass (ubuntu package ssh-askpass).
  2. Create key pairs and protect them by a (hopefully) strong passphrase:
    ~/.ssh$ mkdir mykeys
    ~/.ssh$ cd mykeys
    ~/.ssh/mykeys$ ssh-keygen -t dsa
    Generating public/private dsa key pair.
    Enter file in which to save the key (/home/me/.ssh/id_dsa): /home/me/.ssh/mykeys/gebewau_dsa
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /home/me/.ssh/mykeys/gebewau_dsa.
    Your public key has been saved in /home/me/.ssh/mykeys/gebewau_dsa.pub.
    The key fingerprint is:
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ~/.ssh/mykeys$ chmod 600 *

    To use the keys it is necessary to set strict permission on the files, otherwise ssh won’t accept them.
  3. Edit your .xinitrc (on ubuntu ssh-agent is running by default, see post SSH on Ubuntu , SHH-Agent Is Running per Default), add this line:
    #!/bin/bash
    exec ssh-agent sh -c '{ for f in /home/kostja/.ssh/mykeys/*_dsa ; do ssh-add $f  &lt;/dev/null ; done ; } &amp;&amp;  exec startkde'

    This will start ssh-agent once to use in all sessions. ssh-agent will start a shell (bash in my case) which in turn executes the command enclosed within ‘ ‘. Foreach private key in mykeys directory there will appear a passphrase dialog triggered by ssh-add . The passphrase dialog is provided by x11-ssh-askpass. For this ssh-add reads the SSH_ASKPASS environment variable (in ubuntu it seems not to be neseccary) which you can set in your ~/.bashrc file :

    # Set the location of the x11-ssh-askpass binary
    export SSH_ASKPASS=/usr/local/libexec/x11-ssh-askpass

    On success – startkde will be executed. To see how to run the session independently from the success of the passphrase dialog read the description in Simplifying SSH access using an agent
  4. Configure your ssh client to use agent forwarding by creating and editing the configuration file .ssh/config. An example:
    # selfmade OpenSSH ssh client configuration file will
    # override the system config file in /etc/ssh/ssh_config
    #
    # Config options are unioned over all matching host
    # entries, first config option wins
    
    Host xxx.gebewau.de
    # with this user setting you only have to type
    # ssh xxx.gebewau.de to connect
    User me
    
    Host *.gebewau.de
    # don't need this if identity is added by ssh-add
    #  IdentityFile ~/.ssh/mykeys/gebewau_dsa
    # next two settings have security issues, see man:ssh_config
    ForwardAgent yes
    ForwardX11 yes
    
    Host *
    CheckHostIP yes
    Compression yes
    StrictHostKeyChecking ask
    SetupTimeOut 300
    ServerAliveInterval 300
    
  5. Install your identity.pub in a remote machine’s authorized_keys. You can use scp to copy your public key file to the remote server followed by:
    cat gebewau_dsa.pub &gt;&gt; .ssh/authorized_keys
    Or you use
    ssh-copy-id -i ~/.ssh/mykeys/gebewau_dsa.pub user@xxx.gebewau.de
    this will also set the right permissions in the servers ~/.ssh directory.

To use AgentForwarding you have to use ssh -A or enable forwarding in .ssh/config for the local client and for the client on the bridge server. The bridge servers client will try to use your username you used to log into it. So the set appropriate user names in .ssh/config or use : ssh forwardeduser@over-the-bridge.gebewau.de .

Note about adding several matching identities with ssh-add:
If you have several identities which can access the same host then ssh will only use the first matching one added by ssh-add. Even using command line option -i won’t override it.
So if you have two SSH identities valid on an SSH server, you better don’t load either identity into an agent. Otherwise, one of those identities will be unable to access that server. You may also try to set the config option IdentitiesOnly in your clients config file.

Security remark regarding forwarding found in man:ssh_config:
Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent’s Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent.

Links:

Next Page »