程式狂想筆記

一個攻城師奮鬥史

0%

Shell 實作守護進程方法

Shell 實作守護進程方法

查詢 init.d 守護進程

記錄網路上找的不錯寫法

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

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

start.sh
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

另外一種
看試強制關閉

start_init.sh
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