Linux(CentOS)后台执行命令、运行脚本、注册为服务

后台运行

后台运行Jar

进程后台运行:

1
nohup java -jar xxx.jar&

添加日志

1
nohup java -jar xxx.jar >log.txt &

后台运行程序

1
nohup ./z-wiki >log.txt &

查看进程:

1
ps -ef | grep z-wiki

结束进程:

1
kill -pid

比方说我通过查看进程发现上面运行的jar包的pid是21550,就可以这样结束它:

1
kill 21550

运行脚本

添加脚本

run.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
87
88
89
#!/bin/bash

APP_NAME=z-wiki
ROOT_DIR=$(cd "$(dirname "$0")";pwd)

APP_FILE=${ROOT_DIR}/${APP_NAME}
LOG_DIR=${ROOT_DIR}/logs
PID_FILE=${ROOT_DIR}/logs/${APP_NAME}.pid
LOG_FILE=${ROOT_DIR}/logs/${APP_NAME}.log

function check_pid() {
if [[ -f ${PID_FILE} ]];then
pid=`cat ${PID_FILE}`
if [[ -n ${pid} ]]; then
res=`ps -p ${pid}|grep -v "PID TTY" |wc -l`
return `echo ${res}`
fi
fi
return 0
}

function create_dir() {
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
echo "log dir create success"
fi
}

function start() {
create_dir
check_pid
run_res=$?
if [[ ${run_res} -gt 0 ]];then
echo -n "${APP_NAME} is running already, pid="
cat ${PID_FILE}
return 1
fi
chmod +x ${APP_FILE}
cd ${ROOT_DIR}
nohup ${APP_FILE} &> ${LOG_FILE} &
echo $! > ${PID_FILE}
echo "${APP_NAME} start running, pid=$!"
}

function stop() {
pid=`cat ${PID_FILE}`
kill ${pid}
echo "${APP_NAME} stop"
}

function restart() {
pid=`cat ${PID_FILE}`
stop
start
}

function status() {
check_pid
run_res=$?
if [[ ${run_res} -gt 0 ]];then
echo "status: start"
else
echo "status: stop"
fi
}

function help() {
echo "$0 start|stop|restart|status|pid"
}

function pid() {
cat ${PID_FILE}
}

if [[ "$1" == "" ]]; then
help
elif [[ "$1" == "stop" ]];then
stop
elif [[ "$1" == "start" ]];then
start
elif [[ "$1" == "restart" ]];then
restart
elif [[ "$1" == "status" ]];then
status
elif [[ "$1" == "pid" ]];then
pid
else
help
fi

添加执行权限

1
chmod +x run.sh

运行

启动

1
./run.sh start

停止

1
./run.sh stop

状态

1
./run.sh status

注册为服务

新建文件

新建/etc/init.d/z-wiki.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
87
88
89
90
91
#!/bin/bash
# chkconfig: 2345 85 15
# description:auto_run

APP_NAME=z-wiki
ROOT_DIR=/data/wwwjarapi/8940z-wiki

APP_FILE=${ROOT_DIR}/${APP_NAME}
LOG_DIR=${ROOT_DIR}/logs
PID_FILE=${ROOT_DIR}/logs/${APP_NAME}.pid
LOG_FILE=${ROOT_DIR}/logs/${APP_NAME}.log

function check_pid() {
if [[ -f ${PID_FILE} ]];then
pid=`cat ${PID_FILE}`
if [[ -n ${pid} ]]; then
res=`ps -p ${pid}|grep -v "PID TTY" |wc -l`
return `echo ${res}`
fi
fi
return 0
}

function create_dir() {
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
echo "log dir create success"
fi
}

function start() {
create_dir
check_pid
run_res=$?
if [[ ${run_res} -gt 0 ]];then
echo -n "${APP_NAME} is running already, pid="
cat ${PID_FILE}
return 1
fi
chmod +x ${APP_FILE}
cd ${ROOT_DIR}
nohup ${APP_FILE} &> ${LOG_FILE} &
echo $! > ${PID_FILE}
echo "${APP_NAME} start running, pid=$!"
}

function stop() {
pid=`cat ${PID_FILE}`
kill ${pid}
echo "${APP_NAME} stop"
}

function restart() {
pid=`cat ${PID_FILE}`
stop
start
}

function status() {
check_pid
run_res=$?
if [[ ${run_res} -gt 0 ]];then
echo "status: start"
else
echo "status: stop"
fi
}

function help() {
echo "$0 start|stop|restart|status|pid"
}

function pid() {
cat ${PID_FILE}
}

if [[ "$1" == "" ]]; then
help
elif [[ "$1" == "stop" ]];then
stop
elif [[ "$1" == "start" ]];then
start
elif [[ "$1" == "restart" ]];then
restart
elif [[ "$1" == "status" ]];then
status
elif [[ "$1" == "pid" ]];then
pid
else
help
fi

注意

start的时候一定要添加cd ${ROOT_DIR},否则程序会找不到目录下的文件。

添加执行权限

1
chmod +x /etc/init.d/z-wiki.sh

设置开机启动

首先,添加为系统服务

1
chkconfig --add z-wiki.sh

开机自启动

1
chkconfig z-wiki.sh on

查看

1
chkconfig --list

启动

1
service z-wiki.sh start

停用

1
service z-wiki.sh stop

查看启动情况

1
lsof -i:8940

查看后台程序

如果使用 nohup 后台运行的命令不在当前 shell 会话中,那么 jobs -l 是无法查看这些后台作业的。

可以使用以下几种方式查看

使用ps命令

1
ps -aux | grep "z-wiki"

其中:

  • a:显示所有程序

  • u:以用户为主的格式来显示

  • x:显示所有程序,不以终端机来区分

使用lsof

1
lsof -i:8940

使用pgrep

1
pgrep -f z-wiki

使用top

1
top -p $(pgrep -d',' -f "z-wiki")

命令说明

nohup

如果让程序始终在后台执行,即使关闭当前的终端也执行(之前的&做不到),这时候需要nohup。

该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。

&

加在一个命令的最后,可以把这个命令放到后台执行,如

每10s在后台执行一次test.sh脚本

1
watch -n 10 sh test.sh &

Ctrl + z

可以将一个正在前台执行的命令放到后台,并且处于暂停状态。

bg

将一个在后台暂停的命令,变成在后台继续执行。如果后台中有多个命令,可以用bg %jobnumber将选中的命令调出。

jobs

查看当前有多少在后台运行的命令

1
jobs -l

可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated。但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识。

注意:

jobs -l 主要用于查看在当前 shell 会话中运行的作业及其状态。

如果使用 nohup 后台运行的命令不在当前 shell 会话中,那么 jobs -l 是无法查看这些后台作业的。

fg

将后台中的命令调至前台继续运行。如果后台中有多个命令,可以用fg %jobnumber(是命令编号,不是进程号)将选中的命令调出。

kill

法子1:通过jobs命令查看job号(假设为num),然后执行kill %num
法子2:通过ps命令查看job的进程号(PID,假设为pid),然后执行kill pid
前台进程的终止:Ctrl+c