hunkier

学习笔记,开源代码,技术分享

常用的Shell脚本和Linux命令

收集工作中经常用的Linux命令和shell脚本

zip 压缩和解压缩
1
2
3
4
5
6
7
8
9
# 压缩文件夹
zip -r data.zip data
# 解压缩文件,默认解压到当前路径
unzip data.zip
# 解压到指定路径
unzip data.zip -d destDir
# 查看帮助
unzip -h

tar 压缩和解压缩
1
2
3
4
# 压缩文件夹
tar -czf data.tar.gz data
# 解压缩到当前路径
tar -xzf data.tar.gz -C /destDir
tail查看和过滤日志文件
1
2
3
4
# 动态输出Tomcat日志到控制台
tail -1000f catalina.out
# 按字段过滤日志
tail -1000f catalina.out | grap -A 20 'ERROR'
netstat 查看监听端口的进程
1
2
# 查看监听端口为1600的进程
netstat -tlpn | grep "\b16000\b"
kill停止指定进程
1
2
3
4
5
# 停止当前路径下的应用进程
kill -9 $(ps -ef|grep $(pwd)|grep -v grep|awk '{print $2}')
# 停止监听端口为1600的进程
kill -9 $(netstat -tlpn | grep "\b16000\b" | awk '{print $7}' | cut -d '/' -f 1)

sed替换文件内容
1
2
3
# 替换Tomcat默认端口
sed -i "s|<Connector port=\"8080\"|<Connector port=\"51000\"|g" server.xml && \
sed -i "s|<Connector port=\"8009\"|<Connector port=\"51080\"|g" server.xml
shell 判断文件夹或文件是否存在

文件夹不存在则创建

1
2
3
4
5
if [ ! -d "/data/" ];then
mkdir /data
else
echo "文件夹已经存在"
fi

文件存在则删除

1
2
3
4
5
if [ ! -f "/data/filename" ];then
echo "文件不存在"
else
rm -f /data/filename
fi

判断文件夹是否存在

1
2
3
4
5
if [ -d "/data/" ];then
echo "文件夹存在"
else
echo "文件夹不存在"
fi

判断文件是否存在

1
2
3
4
5
if [ -f "/data/filename" ];then
echo "文件存在"
else
echo "文件不存在"
fi

文件比较符

1
2
3
4
5
6
7
8
9
10
11
12
13
-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新 [ "/data/file1" -nt "/data/file2" ]
-ot 判断file1是否比file2旧 [ "/data/file1" -ot "/data/file2" ]
判断某个变量是否包含字符串/变量的方法

尝试了有3种方法:

  1. 使用“=~”符号,注意前后必须要有空格!

可以输出正确结果,被匹配的字符串必须要有引号括起来!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  ~ a1='hello.world'
➜ ~ a2='helloworld'
➜ ~ b='.'
➜ ~ if [[ ${a1} =~ '.' ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} =~ '.' ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a1} =~ "." ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} =~ "." ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a1} =~ "${b}" ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} =~ "${b}" ]];then echo "yes";else echo "no";fi
yes
➜ ~

不能输出正确结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  ~  a1='hello.world'
➜ ~ '
➜ ~ b='.'
➜ ~ if [[ ${a1} =~ . ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} =~ . ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a1} =~ ${b} ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} =~ ${b} ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a1} =~ '${b}' ]];then echo "yes";else echo "no";fi
no
➜ ~ if [[ ${a2} =~ '${b}' ]];then echo "yes";else echo "no";fi
no
  1. 使用”==“加通配符wildcard,注意等号前后必须有空格,注意,通配符跟正则表达式有所区别,*表示匹配 0 或多个字符

可以输出正确结果

1
2
3
4
5
6
➜  ~  a1='hello.world'
➜ ~ a2='helloworld'
➜ ~ if [[ ${a1} == *.* ]];then echo "yes";else echo "no";fi
yes
➜ ~ if [[ ${a2} == *.* ]];then echo "yes";else echo "no";fi
no

不能输出正确结果 ,通配符不能用括号括起来!

1
2
3
4
5
6
7
8
9
10
➜  ~  a1='hello.world'
➜ ~ a2='helloworld'
➜ ~ if [[ ${a2} == "*.*" ]];then echo "yes";else echo "no";fi
no
➜ ~ if [[ ${a1} == "*.*" ]];then echo "yes";else echo "no";fi
no
➜ ~ if [[ ${a1} == '*.*' ]];then echo "yes";else echo "no";fi
no
➜ ~ if [[ ${a2} == '*.*' ]];then echo "yes";else echo "no";fi
no
  1. 使用echo + grep -q 选项

使用这种方法时匹配是否有”.”会不正常,所以我们换成匹配普通字符,有没有括号都可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
➜  ~  a1='hello.world'
➜ ~ a2='helloworld'
➜ ~ a3="helloworlda"
➜ ~ if ( echo ${a1} |grep -q a );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a2} |grep -q a );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a3} |grep -q a );then echo "yes";else echo "no";fi
yes
➜ ~ if ( echo ${a1} |grep -q 'a' );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a2} |grep -q 'a' );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a3} |grep -q 'a' );then echo "yes";else echo "no";fi
yes
➜ ~ if ( echo ${a1} |grep -q "a" );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a2} |grep -q "a" );then echo "yes";else echo "no";fi
no
➜ ~ if ( echo ${a3} |grep -q "a" );then echo "yes";else echo "no";fi
yes
crontab定时任务
1
2
3
4
5
6
crontab -e
# 每分钟执行一次monitor.sh脚步
*/1 * * * * /usr/java/monitor.sh
# 数据库备份
0 3 * * * /bin/sh /data1/script/databak.sh &
0 4 * * * find /data1/databak -type f -mtime +3 -exec rm {} \;
databak.sh内容
1
2
#!/bin/bash
/usr/bin/mysqldump -uroot -p123456 test >/data1/databak/`date +%Y%m%d`test.sql 2>/dev/null
监控Tomcat是否正常启动
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

#!/bin/sh
# 定义环境变量(要改成自己的jdk相关地址)
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_191-oraclejdk
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
TomcatHome=/opt/webserver/pf-platform

#获取tomcat进程ID(这里注意tomcat7要改成自己的tomcat目录名)
TomcatID=$(ps -ef |grep tomcat |grep -w $TomcatHome|grep -v 'grep'|awk '{print $2}')

#tomcat启动程序(这里注意要改成自己tomcat实际安装的路径)

StartTomcat=$TomcatHome/bin/startup.sh
TomcatCache=$TomcatHome/work

#自己定义要监控的页面地址,页面越简单越好,比如:页面上写个success即可
WebUrl=http://172.20.8.5:41000/pf-platform/login/login

#日志输出 (自己定义地址,用于输出监控日志和监控报错日志)
#TomcatMonitorLog=$TomcatHome/TomcatMonitor-$(date '+%Y%m%d%H%M%S').log
TomcatMonitorLog=$TomcatHome/logs/TomcatMonitor-$(date '+%Y-%m-%d').log
GetPageInfo=$TomcatHome/logs/PageInfo-$(date '+%Y-%m-%d').log
if [ ! -d $TomcatHome/logs ]; then mkdir -p $TomcatHome/logs ; fi
Monitor()
{
echo "[info]开始监控tomcat...[$(date +'%F %H:%M:%S')]"
if [[ $TomcatID ]];then # 这里判断TOMCAT进程是否存在
echo "[info]当前tomcat进程ID为:$TomcatID,继续检测页面..."
# 检测是否启动成功(成功的话页面会返回状态"302")
TomcatServiceCode=$(curl -s -o $GetPageInfo -m 10 --connect-timeout 10 $WebUrl -w %{http_code})
if [ $TomcatServiceCode -eq 302 ];then
echo "[info]页面返回码为$TomcatServiceCode,tomcat启动成功,测试页面正常......"
else
echo "[error]tomcat页面出错,请注意......状态码为$TomcatServiceCode,错误日志已输出到$GetPageInfo"
echo "[error]页面访问出错,开始重启tomcat"
kill -9 $TomcatID # 杀掉原tomcat进程
sleep 3
#rm -rf $TomcatCache # 清理tomcat缓存
$StartTomcat
fi
else
echo "[error]tomcat进程不存在!tomcat开始自动重启..."
echo "[info]$StartTomcat,请稍候......"
#rm -rf $TomcatCache
$StartTomcat
fi
echo "------------------------------"
}

Monitor>>$TomcatMonitorLog

监控netty服务是否正常开启端口
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
#!/bin/sh
# 定义环境变量(要改成自己的jdk相关地址)
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_191-oraclejdk
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
NettyServerHome=/opt/webserver/mtech-cloud-netty-server

#获取netty-server进程ID(这里注意netty-server7要改成自己的netty-server目录名)
NettyServerID=$(ps -ef |grep netty-server |grep -w $NettyServerHome |grep -w java |grep -v 'grep'|awk '{print $2}')

#netty-server启动程序(这里注意要改成自己netty-server实际安装的路径)
StartNettyServer=$NettyServerHome/bin/start.sh

#netty监听端口
NettyPort=16000

#日志输出 (自己定义地址,用于输出监控日志和监控报错日志)
NettyServerMonitorLog=$NettyServerHome/logs/NettyServerMonitor-$(date +'%F').log
GetPageInfo=$NettyServerHome/logs/PortInfo-$(date +'%F').log
if [ ! -d $NettyServerHome/logs ]; then mkdir -p $NettyServerHome/logs ; fi
Monitor()
{
echo "[info]开始监控netty-server...[$(date +'%F %H:%M:%S')]"
if [[ $NettyServerID ]];then # 这里判断netty-server进程是否存在

echo "[info]当前netty-server进程ID为:$NettyServerID,继续检测端口..."
# 检测是否启动成功(成功的话会返回端口信息)
NettyServerPort=$(checkPort $NettyPort)
echo "端口检测结果:$NettyServerPort "
if [ $NettyServerPort -eq 0 ];then
echo "[info]返回码为$NettyServerPort,netty-server启动成功,测试端口正常......"
else
echo "[error]netty-server启动出错,请注意......, 错误日志已输出到$GetPageInfo"
echo "[error]端口$NettyPort检测出错,开始重启netty-server"
kill -9 $NettyServerID # 杀掉原netty-server进程
sleep 3
#rm -rf $netty-serverCache # 清理netty-server缓存
$StartNettyServer >> $NettyServerHome/logs/nohub.out & >> /dev/null
fi
else
echo "[error]netty-server进程不存在!netty-server开始自动重启..."
echo "[info]$StartNettyServer,请稍候......"
#rm -rf $netty-serverCache
# $StartNettyServer >> /dev/null &
$StartNettyServer >> $NettyServerHome/logs/nohub.out & >> /dev/null
fi
echo "------------------------------"
}
checkPort() {
echo "------------------------------" >> $GetPageInfo
echo "$(date +'%F %H:%M:%S') " >> $GetPageInfo
echo $(netstat -tlpn | grep "\b$1\b") >> $GetPageInfo
netstat -tlpn | grep "\b$1\b" | awk '{print $2}'
}
Monitor>>$NettyServerMonitorLog &

部署war包到tomcat
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
➜  web cat start.sh 
WORKDIR=/data1/webserver/mt_chs/web
cd $WORKDIR
kill -9 $(netstat -tlpn | grep "\b18080\b" | awk '{print $7}' | cut -d '/' -f 1)
echo '' > $WORKDIR/logs/catalina.out
$WORKDIR/bin/startup.sh

➜ web cat tailf.sh
WORKDIR=/data1/webserver/mt_chs/web
tail -f $WORKDIR/logs/catalina.out

➜ web cat stop.sh
WORKDIR=/data1/webserver/mt_chs/web
cd $WORKDIR
kill -9 $(netstat -tlpn | grep "\b18080\b" | awk '{print $7}' | cut -d '/' -f 1)

➜ ~ cat deploy_web.sh
WEB_DIR=/data1/webserver/mt_chs/web
APP_DIR=$WEB_DIR/webapps/chs_web
HOME_DIR=/home/ledmon
WAR_FILE=$HOME_DIR/$1


function deploy(){
echo "停止tomcat..."
$WEB_DIR/stop.sh
mkdir -p $APP_DIR
echo "更新应用..."
rm -rf $APP_DIR/*
unzip $WAR_FILE -d $APP_DIR >> /dev/null
echo "启动tomcat..."
$WEB_DIR/start.sh
echo "查看启动日志"
$WEB_DIR/tailf.sh
}

if [ ! -f "$WAR_FILE" ];then
echo "文件不存在,路径: $WAR_FILE"
elif (! echo ${WAR_FILE} |grep -q ".war" );then
echo "文件不合法,路径:$WAR_FILE"
echo "请选择war文件"
elif (! echo ${WAR_FILE} |grep -q "web_product" );then
echo "文件不合法,路径:$WAR_FILE"
echo "请选择web_proeuct*.war文件"
else
deploy
fi
部署springboot的jar包应用
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
➜  appint cat start.sh 
WORKDIR=/data1/webserver/mt_chs/appint
cd $WORKDIR
kill -9 $(netstat -tlpn | grep "\b18083\b" | awk '{print $7}' | cut -d '/' -f 1)
echo '' > $WORKDIR/out.log
nohup java -jar $WORKDIR/appint_*.jar > $WORKDIR/out.log &

➜ appint cat tailf.sh
WORKDIR=/data1/webserver/mt_chs/appint
tail -f $WORKDIR/out.log


➜ ~ cat deploy_appint.sh
APP_DIR=/data1/webserver/mt_chs/appint
HOME_DIR=/home/ledmon
JAR_FILE=$HOME_DIR/$1



function deploy(){
echo "停止应用..."
kill -9 $(netstat -tlpn | grep "\b18083\b" | awk '{print $7}' | cut -d '/' -f 1)
mkdir -p $APP_DIR
echo "更新应用..."
rm -rf $APP_DIR/*.jar
cp $JAR_FILE $APP_DIR
echo "启动应用..."
$APP_DIR/start.sh
echo "查看启动日志"
$APP_DIR/tailf.sh
}

if [ ! -f "$JAR_FILE" ];then
echo "文件不存在,路径: $JAR_FILE"
elif (! echo ${JAR_FILE} |grep -q ".jar" );then
echo "文件不合法,路径:$JAR_FILE"
echo "请选择*.jar文件"
elif (! echo ${JAR_FILE} |grep -q "appint_product" );then
echo "文件不合法,路径:$JAR_FILE"
echo "请选择appint_product*.jar文件"
else
deploy
fi

解压springboot的war包方式运行应用
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

#!/bin/bash
#cat /etc/init.d/api_service_start
### BEGIN INIT INFO
# Provides: hunkier
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The SpringBoot control shell
# Description: Start or stop the SpringBoot application
### END INIT INFO


# 解压war包
# unzip -d $APP_DIR xxx.war

#应用名称
NAME="API_SERVICE"

# springboot 激活的配置文件
PROFILE="product"
# web 应用服务端口
PORT=8080
# 应用部署目录
APP_DIR="/data1/webserver/api_${PORT}"
# 日志目录
LOG_DIR="${APP_DIR}/logs"
# 日志文件
LOG_FILE="${LOG_DIR}/${PORT}.log"
# JVM 参数
VM_OPTIONS="-Xms2g -Xmx2g"
# springboot 参数
SPRING_OPTIONS="--spring.profiles.active=${PROFILE} --server.port=${PORT} --logging.pattern.path=${LOG_DIR}"
JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home"
JAVA_BIN="${JAVA_HOME}/bin/java"

# 引入系统环境
source /etc/profile

# 进入应用目录
cd $APP_DIR
# 创建日志目录
if [ ! -d $LOG_DIR ]; then
mkdir $LOG_DIR
fi

# 创建日志文件
if [ ! -f $LOG_DIR ]; then
touch $LOG_FILE
fi


Info_font_prefix="\033[32m" && Error_font_prefix="\033[31m" && Info_background_prefix="\033[42;37m" && Error_background_prefix="\033[41;37m" && Font_suffix="\033[0m"

RETVAL=0
check_running(){
PID=$(ps -ef |grep ${APP_DIR} |grep $PORT |grep java |grep -v "tail" |grep -v "grep" |grep -v "init.d" |grep -v "service" |awk '{print $2}')
if [[ ! -z ${PID} ]]; then
return 0
else
return 1
fi
}
do_start(){
check_running
if [[ $? -eq 0 ]]; then
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} (PID ${PID}) 正在运行..." && exit 0
else
ulimit -n 51200
cd ${APP_DIR}
do_info
# echo ${APP_DIR}
# echo '' > ${LOG_FILE}
# nohup $JAVA_BIN -cp ${APP_DIR} ${VM_OPTIONS} org.springframework.boot.loader.JarLauncher ${SPRING_OPTIONS} >> /dev/null 2>&1 &
nohup $JAVA_BIN -cp ${APP_DIR} ${VM_OPTIONS} org.springframework.boot.loader.WarLauncher ${SPRING_OPTIONS} >> $LOG_FILE 2>&1 &
# sleep 2s
check_running
if [[ $? -eq 0 ]]; then
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 启动成功 !"
else
echo -e "${Error_font_prefix}[错误]${Font_suffix} ${NAME}_${PORT} 启动失败 !"
fi
fi
}
do_stop(){
check_running
if [[ $? -eq 0 ]]; then
kill -9 ${PID}
RETVAL=$?
if [[ $RETVAL -eq 0 ]]; then
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 停止成功 !"
else
echo -e "${Error_font_prefix}[错误]${Font_suffix} ${NAME}_${PORT} 停止失败 !"
fi
else
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 未运行 !"
RETVAL=1
fi
}
do_status(){
check_running
if [[ $? -eq 0 ]]; then
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} (PID ${PID}) 正在运行..."
else
echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 未运行 !"
RETVAL=1
fi
}
do_tail(){
echo "tail -1000f ${LOG_FILE}"
tail -1000f ${LOG_FILE}
}
do_log(){
echo "tail -f ${LOG_FILE}"
tail -f ${LOG_FILE}
}
do_restart(){
do_stop
do_start
}
do_console(){
do_start
do_log
}
do_info(){
echo "APP_NAME: ${NAME}"
echo "APP_DIR: ${APP_DIR}"
echo "APP_PORT: ${PORT}"
echo "spring 激活配置:${PROFILE}"
echo "日志目录: ${LOG_DIR}"
echo "JAVA_HOME: ${JAVA_HOME}"
echo "VM_OPTIONS: ${VM_OPTIONS}"
echo "SPRING_OPTIONS: ${SPRING_OPTIONS}"
$JAVA_BIN -version
}
case "$1" in
start|stop|restart|status|log|tail|console|info)
do_$1
;;
*)
echo "使用方法: $0 { start(启动) | stop(停止) | restart(重启) | status(状态) | log(日志) | tail(日志) | console(启动并查看日志) | info(配置信息)}"
RETVAL=1
;;
esac
exit $RETVAL




谢谢你请我喝牛奶

欢迎关注我的其它发布渠道