Bagaimana saya bisa menjalankan skrip shell sebagai daemon di bawah Redhat?

12

Saya punya skrip shell, yang pada dasarnya adalah satu liner dengan beberapa logging, yang saya coba jalankan dari skrip init. Saya menggunakan daemonfungsi di dalam /etc/init.d/functionsuntuk menjalankannya, karena Redhat tampaknya tidak start-stop-daemontersedia. Ketika saya memanggil skrip init ( /etc/init.d/script start) ia tetap berada di latar depan, alih-alih menyelesaikan dan membiarkan prosesnya berjalan. Apa cara yang tepat untuk membuat skrip ini di daemonisasi?

Script yang akan dijalankan:

# conf file where variables are defined
. /etc/script.conf

echo "Starting..." | logger -i
echo "Monitoring $LOG_LOCATION." | logger -i
echo "Sending to $MONITOR_HOST:$MONITOR_PORT." | logger -i

tail -n 1 -F $LOG_LOCATION |
grep WARN --line-buffered  |
/usr/bin/nc -vv $MONITOR_HOST $MONITOR_PORT 2>&1 |
logger -i

skrip init:

#!/bin/bash


# Source Defaults
. /etc/default/script

# Source init functions
. /etc/init.d/functions

prog=/usr/local/bin/script.sh

[ -f /etc/script.conf ] || exit 1

RETVAL=0

start()
{
    # Quit if disabled
    if ! $ENABLED; then
            echo "Service Disabled in /etc/default/script"
            exit 1
    fi

    echo "Starting $prog"

    daemon $prog

    RETVAL=$?

    return $RETVAL
}

stop ()
{
    echo -n $"Stopping $prog: "
    killproc $prog

    RETVAL=$?

    return $RETVAL
}

reload()
{
    echo "Reload command is not implemented for this service."
    return $RETVAL
}

restart()
{
    stop
    start
}

condrestart()
{
    echo "Not Implemented."
}

# See how we were called.
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status $prog
        ;;
    restart)
        restart
        ;;
    reload)
        reload
        ;;
    condrestart)
        condrestart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
        RETVAL=1
esac

Terakhir ~ 20 baris eksekusi dengan bash -vx:

+ case "$1" in
+ start
+ true
+ echo 'Starting /usr/local/bin/script.sh'
Starting /usr/local/bin/script.sh
+ daemon /usr/local/bin/script.sh
+ local gotbase= force=
+ local base= user= nice= bg= pid=
+ nicelevel=0
+ '[' /usr/local/bin/script.sh '!=' /usr/local/bin/script.sh ']'
+ '[' -z '' ']'
+ base=script.sh
+ '[' -f /var/run/script.sh.pid ']'
+ '[' -n '' -a -z '' ']'
+ ulimit -S -c 0
+ '[' -n '' ']'
+ '[' color = verbose -a -z '' ']'
+ '[' -z '' ']'
+ initlog -q -c /usr/local/bin/script.sh
bshacklett
sumber
Tampaknya bermanfaat bagi saya bahwa Anda menjalankan skrip itu melalui bash -vx ...dan memposting baris terakhir sehingga kita dapat melihat apa yang ada di latar depan.
Hauke ​​Laging
1
Jangan repot-repot menggunakan hak ini dan menggunakannya daemon, ada paket RPM juga. Btw, ada banyak alat pemantauan log di luar sana ( mulai di sini ).
sr_
Hauke, maksud Anda menggunakan baris pertama #!/bin/bash -vx? Saya mencoba melakukan ini, tetapi tidak menghasilkan output yang sama dari skrip init seperti halnya jika saya menjalankan skrip shell secara langsung.
bshacklett
@ bshacklett Anda dapat memeriksa fungsi skrip init (skrip shell sebenarnya) dengan menjalankannya secara eksplisit bash -vx, yaitu. bash -vx /etc/init.d/script start.
sr_
1
@ bshacklett Wrt log, saya akan melihat logstash lebih dekat . Toko dapat diumpankan log langsung dari Log4j, tetapi agen logstash juga dapat memonitor file log
sr_

Jawaban:

2

Saya menemukan skrip di http://www.linuxforums.org/forum/programming-scripting/190279-daemon-etc-init-d-functions-does-not-return-launching-process.html#post897522 yang saya dapat untuk memodifikasi sesuai dengan kebutuhan saya. Ini secara manual melacak PID dan membuat file PID menggunakan pidof. Saya akhirnya harus memodifikasi ini untuk digunakan pgrepkarena pidoftidak dapat melihat PID dari skrip saya. Setelah modifikasi itu, itu bekerja dengan baik. * Catatan, pgrep tampaknya hanya berfungsi jika nama skrip lengkap kurang dari 15 karakter

Inilah yang akhirnya saya dapatkan:

#!/bin/bash
#
# 
#
# Start on runlevels 3, 4 and 5. Start late, kill early.
# chkconfig: 345 95 05
#
#
#!/bin/bash

# absolute path to executable binary
progpath='/usr/local/bin/script.sh'

# arguments to script
opts=''

# binary program name
prog=$(basename $progpath)

# pid file
pidfile="/var/run/${prog}.pid"

# make sure full path to executable binary is found
! [ -x $progpath ] && echo "$progpath: executable not found" && exit 1

eval_cmd() {
  local rc=$1
  if [ $rc -eq 0 ]; then
    echo '[  OK  ]'
  else
    echo '[FAILED]'
  fi
  return $rc
}

start() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -n "$pids" ]; then
    echo "$prog (pid $pids) is already running"
    return 0
  fi
  printf "%-50s%s" "Starting $prog: " ''
  $progpath $opts &

  # save pid to file if you want
  echo $! > $pidfile

  # check again if running
  pgrep $prog >/dev/null 2>&1
  eval_cmd $?
}

stop() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -z "$pids" ]; then
    echo "$prog not running"
    return 0
  fi
  printf "%-50s%s" "Stopping $prog: " ''
  rm -f $pidfile
  kill -9 $pids
  eval_cmd $?
}

status() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -n "$pids" ]; then
    echo "$prog (pid $pids) is running"
  else
    echo "$prog is stopped"
  fi
}

case $1 in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    sleep 1
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart}"
    exit 1
esac

exit $?
bshacklett
sumber
0

Saya tidak tahu Redhat tetapi daemon $prog &terlihat aneh bagi saya. Jika sudah ada fungsi untuk daemonisasi mengapa harus (dan berguna) menempatkan fungsi ini sendiri di latar belakang? Jadi cobalah tanpa &.

Hauke ​​Laging
sumber
4
Itu tidak salah. /etc/init.d/functionsmendefinisikan daemonfungsi yang mengharapkan argumennya untuk daemonize itu sendiri, ia hanya menangani hal-hal seperti mengubah pengguna, mengatur ulimits, memeriksa (bukan membuat!) sebuah pidfile ... Penggunaan terbaik dari daemonfungsi ini adalah untuk menggantinya dengan libslackdaemon ;)
sr_
Maaf, tanda & ada di sana pada satu titik ketika saya memecahkan masalah. Saya tidak bermaksud untuk memasukkannya dalam posting ini.
bshacklett