Packer Bash Script

Und hier der besagte Script aus dem letzten Post. Unter Linux wird „packer testscript.sh script.sh daten.tgz“ aufgerufen und man bekommt einen Script namens „testscript.sh“ der die datei „daten.tgz“ enthält.

#!/bin/bash
#
# Creates an script with bundled data
#
# Author: Jens Heuschkel <jens@3und20.eu>
#

BANNER="packer v0.1"

PROG=`basename "$0"`
if [ $# -ne 3 -o "$1" == "--help" -o "$1" == "-h" ]; then
  echo $BANNER
  echo "Usage: ${PROG} NEWSCRIPT SCRIPT DATA_TAR"
  echo "       Creates a wrapper called NEWSCRIPT that wraps the"
  echo "       specified SCRIPT and appends the DATA_TAR"
  echo ""
  echo "   or: ${PROG} -h|--help"
  echo "       Prints this message."
  exit 0
fi

NEWSCRIPT=$1
SCRIPT=$2
DATA_TAR=$3

echo $BANNER
echo "Checking files.."

if [ ! -e ${SCRIPT} ]
then
 echo "Script \"${SCRIPT}\" not found." >&2
 exit 1
fi

if [ ! -e ${DATA_TAR} ]
then
 echo "Data \"${DATA_TAR}\" not found." >&2
 exit 1
fi

touch $NEWSCRIPT
if [ ! -e ${NEWSCRIPT} ]
then
 echo "Can't write \"${NEWSCRIPT}\". Check rights." >&2
 exit 1
fi

# Get size
TAR_SIZE=`stat -c %s ${DATA_TAR}`

#SPLIT_CMD="tail -c ${TAR_SIZE} \$0 | tar -xz ${DATA_TAR}"
SPLIT_CMD="tail -c ${TAR_SIZE} \$0 > ${DATA_TAR}"

# Write untar part
cat > ${NEWSCRIPT} <> $NEWSCRIPT

cat >> ${NEWSCRIPT} <<'EOF' exit # Data goes here EOF cat $DATA_TAR >> $NEWSCRIPT

chmod +x $NEWSCRIPT
echo "done"
exit 0

Der Script funktioniert nach dem Vorbild von jar2sh von martiansoftware

Quelle:
http://www.martiansoftware.com/lab/jar2sh.html

More Bash

Uns schon wieder eine kleine Bash Weisheit….
Ich bastel gerade an einem Script der Scripte und Tar-Daten in eine Datei packt. Ist ganz praktisch für install Scripte die eigene Daten mitbringen sollen.

Das Ganze funktioniert so:

  • Der Script schreibt ein paar Zeilen um die Daten weg zu splitten
  • Dann wird der eigentlich Script geschrieben
  • Dann die Tar-Daten (einfach mit cat)

Beim ausführen werden die Daten einfach vom Ende weg kopiert und dann verhält sich der Script die der Ursprungsscript.

Und in dem Zusammnhang habe ich eine spielerei mit cat entdeckt:

  • cat > ZIELDATEI <<EOF schreibt die folgenden Zeilen bis EOF kommt.
  • cat > ZIELDATEI <<‚EOF‘ macht das gleiche 😀

Ich hab mich jetzt gefragt wo der unterschied ist, weil ich beides in einem Script gesehen habe.
Bei der version mit ‚EOF‘ werden Variablen nicht aufgelöst und bei EOF schon. Gut zu wissen 🙂

Java Server als Daemon auf Debian Linux

Ich habe einige Tage nach einer einfachen Möglichkeit gesucht, meine Java Programme als Daemon auf Debian Linux zu starten. Es gibt einiges an Scripten für SuSe und davon auch Portierungen auf Debian. Allerdings fand‘ ich diese Implementierungen immer unnötig kompliziert und unübersichtlich.

Gestern bin ich endlich auf eine einfache und klar programmierte Lösung gestossen. Ein einfacher Wrapperskript der alle benötigten Funktionen unterstützt. Der Skript ist von 2009 läuft aber noch einwandfrei. Allerdings ist er nicht auf Debian spezialisiert und ist für die KSH geschrieben. Ich bin mal alles durchgegangen und habe einige Anpassungen gemacht. Herausgekommen ist folgende Debian interpretation:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Java Daemon Script
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

# Author: Jens Heuschkel <jens@3und20.eu>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin

APP_NAME="MyApp"
APP_LONG_NAME="My App Server"

#the location of the pid files.
PIDDIR="/var/run"
PIDFILE="${PIDDIR}/${APP_NAME}.pid"
TIMESTAMP=$( date +%Y%m%d_%H%M%S )

#number of seconds to wait after starting up.
WAIT_AFTER_STARTUP=2

#the location of the log files
LOG_DIR="/var/log"
STDOUT="${LOG_DIR}/${APP_NAME}.stdout.log"

#PURGE_EXPRESSION="-mtime +2"
PURGE_EXPRESSION="${LOG_DIR}/${APP_NAME}*"

HEAPSIZE_INIT=16
HEAPSIZE_MAX=100
VMARGS="-Xms${HEAPSIZE_INIT}M -Xmx${HEAPSIZE_MAX}M -verbose:gc"
MAINCLASS="com.wordpress.jensheuschkel.MyApplication"
JARFILE="MyApp.jar"
ARGS=""

JAVA_COMMAND="/usr/bin/java"

# Startup with Classpath
#START_COMMAND="${JAVA_COMMAND} $VMARGS $MAINCLASS $ARGS"
# Startup with jar
START_COMMAND="${JAVA_COMMAND} $VMARGS -jar ${JARFILE} ${ARGS}"
#-----------------------------------------------------------------------------
# Do not modify anything beyond this point
#-----------------------------------------------------------------------------

checkroot() {
 if [[ $EUID -ne 0 ]]; then
  echo "This script must be run as root" 1>&2
  exit 1
 fi
}

getpid() {
  pid=""
  if [ -f "$PIDFILE" ]
  then
    if [ -r "$PIDFILE" ]
    then
      pid=`cat "$PIDFILE"|cut -d: -f1`
      host=`cat "$PIDFILE"|cut -d: -f2`
      currhost=`hostname`
      if [ "$host" != "$currhost" ]
      then
       echo "You are on the wrong host. $APP_LONG_NAME runs on $host."
       exit 1
      fi

      if [ "X$pid" != "X" ]
      then
       kill -0 $pid > /dev/null 2>&1
  if [ $? -ne 0 ]
  then
   # Process doesn't exist, so remove pidfile
   rm -f "$PIDFILE"
            echo "Removed stale pid file: $PIDFILE"
   pid=""
  fi
      fi
    else
      echo "Cannot read $PIDFILE."
      exit 1
    fi
  fi
}

#tests if the pid is alive
testpid() {
  kill -0 $pid > /dev/null 2>&1
  if [ $? -ne 0 ]
  then
   # Process is gone so remove the pid file.
 rm -f "$PIDFILE"
 pid=""
  fi
}

start() {
  echo "Starting $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    if [ -s $STDOUT ]
    then
     #backup current file
     mv $STDOUT $STDOUT.sav.${TIMESTAMP}
    fi
    echo CLASSPATH is $CLASSPATH > $STDOUT
    echo ${START_COMMAND} >> $STDOUT
    nohup ${START_COMMAND} >> $STDOUT 2>&1 &
    echo $!:`hostname` > $PIDFILE
  else
    echo "$APP_LONG_NAME is already running."
    exit 1
  fi

  # Sleep for a few seconds to allow for intialization if required
  # then test to make sure we're still running.
  i=0
  while [ $i -lt $WAIT_AFTER_STARTUP ]
  do
    sleep 1
    i=`expr $i + 1`
  done
  if [ $WAIT_AFTER_STARTUP -gt 0 ]
  then
    getpid
    if [ "X$pid" = "X" ]
    then
      echo "WARNING: $APP_LONG_NAME may have failed to start."
      exit 1
    else
      echo "running ($pid)."
    fi
  else
    echo ""
  fi
}

stopit() {

  echo "Stopping $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME was not running."
  else
    # Running so try to stop it.
    kill $pid
    if [ $? -ne 0 ]
    then
      echo "Unable to stop $APP_LONG_NAME."
      exit 1
    fi

    #  If it has not stopped in 10 tries, forcibly kill it
    savepid=$pid
    CNT=0
    TOTCNT=0
    while [ "X$pid" != "X" ]
    do
      # Show a waiting message every 5 seconds.
      if [ "$CNT" -lt "5" ]
      then
        CNT=`expr $CNT + 1`
      else
        echo "Waiting for $APP_LONG_NAME to exit..."
        CNT=0
      fi

      if [ $TOTCNT -gt 11 ]
      then
       echo "Killing by force (kill -9)"
       kill -9 $pid
      fi

      TOTCNT=`expr $TOTCNT + 1`
      sleep 1

      testpid
    done

    pid=$savepid
    testpid
    if [ "X$pid" != "X" ]
    then
      echo "Failed to stop $APP_LONG_NAME."
      exit 1
    else
      echo "Stopped $APP_LONG_NAME."
    fi
  fi
}

purge() {
#  pcmd="find $LOG_DIR -follow -type f $PURGE_EXPRESSION -print -exec rm -f {} +"
  pcmd="rm -f ${PURGE_EXPRESSION}"
  echo "Running purge: $pcmd"
  $pcmd
}

alert() {
  if [ "X$EMAIL" != "X" ]
  then
   echo "$APP_LONG_NAME is not running on `hostname`. Please check and restart." \
   | mailx -s "`hostname`: $APP_LONG_NAME is not running" "$EMAIL"
   echo "Sent alert to $EMAIL"
  fi
}

status() {
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME is not running."
    alert
    exit 1
  else
    echo "$APP_LONG_NAME is running (PID:$pid)."
    exit 0
  fi
}

dump() {
  echo "Dumping $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME is not running."
  else
    kill -3 $pid

    if [ $? -ne 0 ]
    then
      echo "Failed to dump $APP_LONG_NAME."
      exit 1
    else
      echo "Dumped $APP_LONG_NAME."
    fi
  fi
}

####################

checkroot

case "$1" in

  'start')
    start
    ;;

  'stop')
    stopit
    ;;

  'restart')
    stopit
    start
    ;;

  'status')
    status
    ;;

  'dump')
    dump
    ;;

  'purge')
    purge
    ;;

  *)
    echo "Usage: $0 { start | stop | restart | status | dump | purge }"
    exit 1
    ;;
esac

exit 0

 

Die VM Einstellungen sind für das Rapberry Pi und sollten noch angepasst werden. Es wird auch nicht gecheckt ob JAVA installiert ist aber das kann man ja im Install-Skript des Servers machen 😉

Quelle:
http://fahdshariff.blogspot.de/2009/09/unix-wrapper-script-for-java.html

Bash IF Conditions

Jaja schon wieder Bash :DIch vergesse einfach ständig die Syntax und aufschreiben ist das Einzige das ein bisschen hilft.
Mal „unter uns“: Bash ist auch eine der anstrengensten Skriptsprachen überhaupt …

Also diesmal geht es um IF Conditions. Grundsätzlich funtkioniert es wie folgt:

if [ <condition> ]then

elif [ <condition> ]
then

else

fi

Das allein finde ich schon unintuitiv: „elif“ statt „else if“ und then in einer neuen Zeile. Alternativ kann man auch „; then“ in der gleichen Zeile schreiben. Abgeschlossen wird das ganze mit „if“ rückwärts, also „fi“. Aufpassen, denn die Leerzeichen vor und nach den Klammern sind nicht optional!

Nun nun zu den Conditions:

  • [ -e filepath ] wird true wenn die Datei existiert.
  • [ -x filepath ] wird true wenn die Datei existiert und ausführbar ist.
  • [ -S filepath ] wird true wenn die Datei existiert und eine Socket-Datei ist.
  • [ -d filepath ] wird true wenn die Datei existiert und ein Verzeichnis ist.
  • [ -w filepath ] wird true wenn die Datei existiert und schreibbar ist.
  • [ expr1 -a expr2 ] entspricht dem logischen AND (Java: &&)
  • [ expr1 -o expr2 ] entspricht dem lofischen OR (Java: || )
  • [ -n $VARIABLE ] wird true wenn die Varable (also der String) nicht leer ist.
  • [ -z $VARIABLE ] wird true wenn die Varable (also der String) leer ist (Java: „foo“.isEmpty() ).
  • [ $VARIABLE = $VARIABLE2 ] wird true wenn die beiden Variablen gleich sind (Java: „foo“.equals(„foo“) ).
    ACHTUNG: Das funktioniert nur mit Strings und nicht mit Zahlen und ist Case-Sensitiv.
  • [ $VARIABLE -eq $VARIABLE2 ] wird true wenn die beiden Variablen die gleich Zahl enthalten (Java: == ).
  • [ $VARIABLE -lt $VARIABLE2 ] wird true wenn die 1. Variable kleiner ist (Java: < ).
  • [ $VARIABLE -gt $VARIABLE2 ] wird true wenn die 1. Variable größer ist (Java: > ).
  • [ $VARIABLE -le $VARIABLE2 ] wird true wenn die 1. Variable kleiner oder gleich ist (Java: <= ).
  • [ $VARIABLE -ge $VARIABLE2 ] wird true wenn die 1. Variable gößer oder gleich ist (Java: >= ).
  • [ $VARIABLE -ne $VARIABLE2 ] wird true wenn die beiden Variablen ungleich sind (Java: != ).
  • [ ! <condition> ] negiert die condition (Java: ! ).

Es gibt noch einige mehr, aber ich denke das sind die Wichtigsten.

Quellen:
http://wiki.ubuntuusers.de/Shell/Bash-Skripting-Guide_f%C3%BCr_Anf%C3%A4nger
http://www.thegeekstuff.com/2010/06/bash-conditional-expression/

Bash Intermezzo

Hier mal eine kleine mini Bash Hilfe. Ich vergesse immer wie man Strings richtig concatiniert :D.Man kann es so machen:

  • VARIABLE=“String“
    NEUE_VARIABLE=“Neu“VARIABLE

Sieht für mich aber sehr Fehleranfällig aus. Die richtige Version ist:

  • VARIABLE=“Sring“
    NEUE_VARIABLE=“Neu${VARIABLE}“