Contents

Shell 實作守護進程方法

Shell 實作守護進程方法

查詢 init.d 守護進程

記錄網路上找的不錯寫法

以下參考springboot 打包(jar)部署在 Linux 環境 - SegmentFault 思否
這個應該也能改成一般程式執行

注意!!這邊不是無限loop
估記是Java 程式做 loop

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/bin/bash

AppName=ruoyi.jar

#JVM參數
JVM_OPTS="-Dname=$AppName  -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps  -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log

if [ "$1" = "" ];
then
    echo -e "\033[0;31m 未輸入操作名 \033[0m  \033[0;34m {start|stop|restart|status} \033[0m"
    exit 1
fi

if [ "$AppName" = "" ];
then
    echo -e "\033[0;31m 未輸入應用名 \033[0m"
    exit 1
fi

function start()
{
    PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`

    if [ x"$PID" != x"" ]; then
        echo "$AppName is running..."
    else
        nohup java -jar  $JVM_OPTS target/$AppName > /dev/null 2>&1 &
        echo "Start $AppName success..."
    fi
}

function stop()
{
    echo "Stop $AppName"
    
    PID=""
    query(){
        PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
    }

    query
    if [ x"$PID" != x"" ]; then
        kill -TERM $PID
        echo "$AppName (pid:$PID) exiting..."
        while [ x"$PID" != x"" ]
        do
            sleep 1
            query
        done
        echo "$AppName exited."
    else
        echo "$AppName already stopped."
    fi
}

function restart()
{
    stop
    sleep 2
    start
}

function status()
{
    PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
    if [ $PID != 0 ];then
        echo "$AppName is running..."
    else
        echo "$AppName is not running..."
    fi
}

case $1 in
    start)
    start;;
    stop)
    stop;;
    restart)
    restart;;
    status)
    status;;
    *)

esac

另外一種
看試強制關閉

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/sh
JAR_NAME=ruoyi.jar

tpid=`ps -ef|grep $JAR_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Stop Process...'
fi
sleep 5
tpid=`ps -ef|grep $JAR_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Kill Process!'
kill -9 $tpid
else
echo 'Stop Success!'
fi

tpid=`ps -ef|grep $JAR_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
        echo 'App is running.'
else
        echo 'App is NOT running.'
fi

rm -f tpid
nohup java -jar ./$JAR_NAME >/dev/null 2>&1 &
echo $! > tpid
echo 'Start Success!'

這個應該可以改成一般非 Java 程式排程
再搭配關閉訊號控制程式,是不是就是完美關閉腳本
好吧,其實我還是覺得 Systemd 才是最佳解決方案

關閉訊號控制程式

最近有看到可以傳送關閉訊號控制程式跑完進程關閉程式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash

mp3convert () {
  echo "mp3convert..."; sleep 5; echo "mp3convert done..."
}

PreTrap() {
  echo "in trap"
  QUIT=1
  echo "exiting trap..."
}

CleanUp() {
  ### Since 'wait $PID' can be interrupted by ^C, we need to protected it
  ### by the 'kill' loop  ==> double/triple control-C problem.
  while kill -0 $PID >& /dev/null; do wait $PID; echo "check again"; done

  ### This won't work (A simple wait $PID is vulnerable to double control C)
  # wait $PID

  if [ ! -z $QUIT ]; then
     echo "clean up..."
     exit
 fi
}

trap PreTrap SIGINT SIGTERM SIGTSTP
#trap CleanUp EXIT

for loop in 1 2 3; do
    (
      echo "loop #$loop"
      mp3convert
      echo magic 1
      echo magic 2
      echo magic 3
    ) &
    PID=$!
    CleanUp
    echo "done loop #$loop"
done

測試結果,還真的有用
開兩個 cmd ,一個執行,另一個kill
並不會直接結束

參考:shell - bash trap interrupt command but should exit on end of loop - Stack Overflow

trap 相關指令,可以用來可以控制關閉方法

調整完美關閉腳本

TODO: 待修改

彩蛋

執行 Docker 容器可使用 dumb-init 或 tini 改善程序優雅結束的問題 | The Will Will Web