nginx是一款著名的開源web服務(wù)器,為方便升級與恢復(fù),編寫了一個簡單的腳本,因為升級備份了可執(zhí)行文件和配置文件(后綴名為old),所以可用于恢復(fù)。當升級時,若nginx正在運行,則不中斷服務(wù)進行平滑升級,否則直接拷貝覆蓋;當恢復(fù)時,若nginx正在運行,則不中斷服務(wù)進行平滑恢復(fù),否則直接拷貝覆蓋。是否正在運行根據(jù)pid來判斷,而pid從pid文件讀取,pid文件則從conf文件提取(默認為/usr/local/nginx/logs/nginx.pid)。對于參數(shù)指定的conf文件,會分析它是否存在http {和server {行來檢查有效性。該腳本的用法如下:
● 第1參數(shù)必須為upgrade或restore,分別表示升級或恢復(fù)。
● 第2參數(shù)是可選的,為nginx可執(zhí)行文件,默認為/usr/local/nginx/sbin/nginx。
● 第3參數(shù)是可選的,為nginx配置文件,默認為/usr/local/nginx/conf/nginx.conf。
腳本實現(xiàn)
在循環(huán)讀取配置文件每一行時,首先要忽略空白行和注釋行,對應(yīng)正則式分別為^$、^[[:blank:]]*#;然后識別http {或server {行,對應(yīng)正則式分別為^[[:blank:]]*http[[:blank:]]*{[[:blank:]]*、^[[:blank:]]*server[[:blank:]]*{[[:blank:]]*。不管恢復(fù)還是升級,當替換nginx可執(zhí)行文件后,如果nginx正在運行(一定要使用mv替換才能成功),先發(fā)送USR2信號(通知nginx創(chuàng)建新的工作進程)并等待老的pid文件出現(xiàn),再發(fā)送QUIT使老的nginx工作進程退出。
1
#! /bin/bash
2
# nginx admin script
3
4
. extfuncs
5
6
usage()
7
{
8
echo "Usage: $(basename "$0") upgrade|restore [executable file] [configure file]"
9
exit 1
10
}
11
12
if [ $# -lt 1 ]; then
13
usage
14
elif [ "$1" != "upgrade" -a "$1" != "restore" ]; then
15
echo "The first parameter must be upgrade or restore"
16
exit 1
17
fi
18
19
do_restore=no
20
[ "$1" = "restore" ] && do_restore=yes
21
22
bin_file=${2:-/usr/local/nginx/sbin/nginx}
23
! check_file_exist "$bin_file" && usage
24
25
if [ ! -x "$bin_file" ]; then
26
echo "$bin_file: Permission denied"
27
exit 1
28
fi
29
30
conf_file=${3:-/usr/local/nginx/conf/nginx.conf}
31
! check_file_exist "$conf_file" && usage
32
33
re_0="[[:blank:]]"
34
re_1="$re_0*"
35
re_2="^$re_1"
36
re_3="$re_0+.+"
37
re_4="$re_2#"
38
re_http="${re_2}http${re_1}{${re_1}"
39
re_server="${re_2}server${re_1}{${re_1}"
40
re_pid="${re_2}pid$re_3"
41
42
has_http=
43
has_server=
44
pid_file=
45
46
while read line
47
do
48
if (echo $line | grep "^$" > /dev/null) || (echo $line | grep "$re_4" > /dev/null); then
49
continue
50
elif (echo $line | grep "$re_http" > /dev/null); then
51
has_http=yes
52
elif (echo $line | grep "$re_server" > /dev/null); then
53
has_server=yes
54
test -n "$pid_file" || pid_file=`echo $line | awk '{if($0~/'"$re_pid"'/) print substr($2,1,index($2,";")-1)}'`
55
test -n "$pid_file" && break
56
done < "$conf_file"
57
58
if [ "x$has_http" != "xyes" -o "x$has_server" != "xyes" ]; then
59
echo "$conf_file is not valid nginx configure file"
60
exit 1
61
fi
62
63
if [ -z "$pid_file" ]; then
64
pid_file=/usr/local/nginx/logs/nginx.pid
65
elif [ "${pid_file,0,1}" != "/" ]; then
66
pid_file=/usr/local/nginx/$pid_file
67
fi
68
69
[ "x$do_restore" = "xno" ] && ! check_file_exist nginx && exit 1
70
[ "x$do_restore" = "xyes" ] && ! check_file_exist "${bin_file}.old" && exit 1
71
[ "x$do_restore" = "xyes" ] && ! check_file_exist "${conf_file}.old" && exit 1
72
73
pid=$(get_pid "$pid_file")
74
check_pid $pid
75
ret=$?
76
77
if [ "$ret" -eq "0" ]; then
78
if [ "x$do_restore" = "xno" ]; then
79
mv "$bin_file" "${bin_file}.old"
80
cp "$conf_file" "${conf_file}.old"
81
else
82
mv "$bin_file" "${bin_file}.tmp"
83
fi
84
echo -n "nginx is running($pid),"
85
else
86
echo -n "nginx is not run,"
87
fi
88
89
if [ "x$do_restore" = "xno" ]; then
90
echo "upgrading it"
91
else
92
echo "restoring it"
93
fi
94
95
if [ "x$do_restore" = "xno" ]; then
96
cp -f nginx $bin_file
97
else
98
mv "${bin_file}.old" "$bin_file"
99
mv "${conf_file}.old" "$conf_file"
100
fi
101
102
$bin_file -t -v -c "$conf_file"
103
104
if [ "$ret" -eq "0" ]; then
105
kill -USR2 $pid
106
wait_file "${pid_file}.oldbin"
107
kill -QUIT `cat "${pid_file}.oldbin"`
108
[ "x$do_restore" = "xyes" ] && rm -f "${bin_file}.tmp"
109
fi
110
111
if [ "x$do_restore" = "xno" ]; then
112
echo "upgrade nginx finished"
113
else
114
echo "restore nginx finished"
115
fi

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

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

腳本示例
升級前:nginx正在運行中,由于此時還沒升級,所以沒有old備份文件,如下圖

升級后:運行./ngxadmin upgrade后,如下圖

從上可得,sbin和conf子目錄下分別多出了一個nginx.old和nginx.conf.old。
恢復(fù)后:運行./ngxadmin restore后,如下圖

從上可得,sbin子目錄下沒有了nginx.old,conf子目錄下沒有了nginx.conf.old,nginx可執(zhí)行文件和配置文件均已恢復(fù)為升級前的版本。