
Shell
sed常用替换小技巧记录
运维 Something 发表了文章 0 个评论 1427 次浏览 2020-08-20 14:48
sed 's/^[ \t]*//g'
2. 去掉行末空格sed 's/[ \t]*$//g'
3. 去掉所有空格sed s/[[:space:]]//g4. 替换符号
sed "s/^\(.*\)$/'\1'/"
sed "s/^\(.*\)$/aa =>\1/"
Shell脚本判断变量或者文件是否存在案例
运维 Rock 发表了文章 0 个评论 4186 次浏览 2017-02-22 14:50
脚本代码1:
#!/bin/bash
# site: openskill.cn
myPath="/data/logs"
myFile="/data/logs/access.log"
# 这里的-x 参数判断$myPath是否存在并且是否具有可执行权限
if [ ! -x "$myPath"];then
mkdir "$myPath"
fi
# 这里的-d 参数判断$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi
# 这里的-f参数判断$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi
# 其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi
# 两个变量判断是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 ne $var2'
fi
脚本代码2:
#/bin/bash
#如果文件夹不存在,创建文件夹
if [ ! -d "/data" ]; then
mkdir /data
fi
#shell判断文件,目录是否存在或者具有权限
folder="/data/www"
file="/data/www/log"
# -x 参数判断 $folder 是否存在并且是否具有可执行权限
if [ ! -x "$folder"]; then
mkdir "$folder"
fi
# -d 参数判断 $folder 是否存在
if [ ! -d "$folder"]; then
mkdir "$folder"
fi
# -f 参数判断 $file 是否存在
if [ ! -f "$file" ]; then
touch "$file"
fi
# -n 判断一个变量是否有值
if [ ! -n "$var" ]; then
echo "$var is empty"
exit 0
fi
# 判断两个变量是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 ne $var2'
fi
shell中条件判断if中的-a到-z的意思
运维 Rock 发表了文章 0 个评论 2042 次浏览 2017-02-15 18:03
[ -a FILE ] 如果 FILE 存在则为真。
[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 FILE 存在则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
[ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小不为0则为真。
[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2,or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
[ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。
[ -z STRING ] “STRING” 的长度为零则为真。
[ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。
[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.
数字判断
[ $count -gt "1"] 如果$count 大于1 为真
-gt 大于
-lt 小于
-ne 不等于
-eq 等于
-ge 大于等于
-le 小于等于
[ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。
[ STRING1 != STRING2 ] 如果字符串不相等则为真。
[ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。
[ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。
Shell下判断一个命令是否存的最好方法
运维 Rock 发表了文章 0 个评论 4824 次浏览 2017-02-15 15:22
通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。
1、which非SHELL的内置命令,用起来比内置命令的开销大,并且非内置命令会依赖平台的实现,不同平台的实现可能不同。
[root@node1 ~]# type scp从上面可以看出command为内置命令,而which非内置命令。
scp is /usr/bin/scp
[root@node1 ~]# type command
command is a shell builtin
[root@node1 ~]# type which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
2、很多系统的which并不设置退出时的返回值,即使要查找的命令不存在,which也返回0
[root@node1 ~]# which ls所以许多系统的which实现,都偷偷摸摸干了一些“不足为外人道也”的事情。
/usr/bin/ls
[root@node1 ~]# echo $?
0
[root@node1 ~]# which www
no www in /usr/bin /bin /usr/sbin /sbin /usr/local/bin /usr/local/bin /usr/local/sbin /usr/ccs/bin
[root@node1 ~]# echo $?
0
所以,不要用which,可以使用下面的方法:
$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
The following is a portable way to check whether a command exists in PATH and is executable:更精彩的分析参考:http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script
[ -x "$(command -v foo)" ]
Example:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
运维如何写出不耍流氓的Shell脚本
运维 小白菜 发表了文章 3 个评论 2834 次浏览 2016-12-02 22:33

声明
大家都是文明人,尤其是做运维的,那叫一个斯文啊。怎么能耍流氓呢?赶紧看看,编写 SHELL 脚本如何能够不耍流氓。
MySQL备份脚本案例
1、不记录日志的shell
脚本就是耍流氓!
我们经常在工作中会遇到一个苦恼的事情,一个 Shell 脚本到底干了什么,什么时候开始执行,什么时候结束的。尤其是数据库备份,我们想知道我们的 MySQL 数据库备份时间。所以给脚本加日志显得尤为重要。那么我们的脚本应该有一个日志的函数,专门用于记录日志:
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
shell_log "shell beginning, Write log test"
shell_log "shell success, Write log test"
上面的脚本我编写了一个日志函数shell_log,每次记录日志,我们直接执行shell_log把日志内容当作第一个参数传给它就可以了,赶紧试试。
[root@labs shell]# cat shell_template.sh.log
2016-08-27 06-01-19 : shell_template.sh :shell beginning ,write log test
2016-08-27 06-01-19 : shell_template.sh :shell success ,write log test
2、直接就能执行的Shell脚本很容易耍流氓
一个脚本直接就能执行?难道不是直接就能执行吗?试想,你临时编写了一个特别重要的脚本,干的事情可能有破坏性,一不小心被别人./执行了怎么办呢?而且很多时候我们一个脚本的功能可能有多个,所以我们有必要让用户可以选择进行执行。
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
# Shell Usage
shell_usage(){
echo $"Usage: $0 {backup}"
}
# Backup MySQL All Database with mysqldump or innobackupex
mysql_backup(){
shell_log "mysql backup start"
shell_log "mysql backup stop"
}
# Main Function
main(){
case $1 in
backup)
mysql_backup
;;
*)
shell_usage;
esac
}
#Exec
main $1
上面的脚本我们编写了shell_usage函数,用来告诉用户,这个脚本的使用方法。同时,我要强调一下,像编写Shell, 我们经常是面向过程的,建议以函数为单位,这样脚本非常的清晰可读。赶紧执行以下看看效果吧。
[root@labs shell]# ./shell_template.sh
Usage: ./shell_template.sh {backup}
3、不加锁的Shell脚本就是让别人耍流氓
你编写的脚本能多个人同时执行吗?如果不能,那么如果多个人一起执行会怎么样呢?想想是不是有点冒冷汗。所以,不要给我们的其它小伙伴留下陷阱。不过如果你公司就你一个运维,真的不用怕吗?试想如果是定时任务再运行这个脚本,上一次没有运行完毕,然后到时间又运行了?然后,然后,然后,后果好可怕。
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
# Shell Usage
shell_usage(){
echo $"Usage: $0 {backup}"
}
shell_lock(){
touch ${LOCK_FILE}
}
shell_unlock(){
rm -f ${LOCK_FILE}
}
# Backup MySQL All Database with mysqldump or innobackupex
mysql_backup(){
if [ -f "$LOCK_FILE" ];then
shell_log "${SHELL_NAME} is running"
echo "${SHELL_NAME}" is running && exit
fi
shell_log "mysql backup start"
shell_lock
sleep 10
shell_log "mysql backup stop"
shell_unlock
}
# Main Function
main(){
case $1 in
backup)
mysql_backup
;;
*)
shell_usage;
esac
}
#Exec
main $1
我为脚本增加了两个函数shell_lock和shell_unlock非常简单,就是创建一个锁文件。然后再执行的时候先判断锁文件是否存在,如果存在说明有其它用户在执行,就退出。如果没有自己创建锁文件,开始执行,执行完毕删除锁文件。
好的,现在你可以赶紧再开一个窗口试试能不能执行这个脚本,或者到/tmp目录下看看是否创建了锁文件。请注意:如果已知的异常退出,一定也要删除这个锁文件。
一般创建锁文件放到/var/lock/subsys/
目录下,比如postfix的锁文件就是:
prog="postfix"
lockfile=/var/lock/subsys/$prog
做好事须留名
对于一个功能脚本来说,貌似还少了点什么。对,就是注释!我们要说明白这个脚本是干啥的。或者以后你离职后,别人看到这个脚本之后,我擦,这么牛掰的脚本是谁写的呢?不要怕,写上你的大名。
#######################################################
# $Name: shell_template.sh
# $Version: v1.0
# $Function: Backup MySQL Databases Template Script
# $Author: Jason Zhao
# $organization: https://www.baidu.com
# $Create Date: 2016-08-27
# $Description: You know what i mean,hehe
#######################################################
当然还有很多编写脚本的技巧,没法一一描述,不过如果能掌握上面的三种技巧,立马感觉编写的脚本有点高大上,有木有?
sed常用替换小技巧记录
运维 Something 发表了文章 0 个评论 1427 次浏览 2020-08-20 14:48
sed 's/^[ \t]*//g'
2. 去掉行末空格sed 's/[ \t]*$//g'
3. 去掉所有空格sed s/[[:space:]]//g4. 替换符号
sed "s/^\(.*\)$/'\1'/"
sed "s/^\(.*\)$/aa =>\1/"
Shell脚本判断变量或者文件是否存在案例
运维 Rock 发表了文章 0 个评论 4186 次浏览 2017-02-22 14:50
脚本代码1:
#!/bin/bash
# site: openskill.cn
myPath="/data/logs"
myFile="/data/logs/access.log"
# 这里的-x 参数判断$myPath是否存在并且是否具有可执行权限
if [ ! -x "$myPath"];then
mkdir "$myPath"
fi
# 这里的-d 参数判断$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi
# 这里的-f参数判断$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi
# 其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi
# 两个变量判断是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 ne $var2'
fi
脚本代码2:
#/bin/bash
#如果文件夹不存在,创建文件夹
if [ ! -d "/data" ]; then
mkdir /data
fi
#shell判断文件,目录是否存在或者具有权限
folder="/data/www"
file="/data/www/log"
# -x 参数判断 $folder 是否存在并且是否具有可执行权限
if [ ! -x "$folder"]; then
mkdir "$folder"
fi
# -d 参数判断 $folder 是否存在
if [ ! -d "$folder"]; then
mkdir "$folder"
fi
# -f 参数判断 $file 是否存在
if [ ! -f "$file" ]; then
touch "$file"
fi
# -n 判断一个变量是否有值
if [ ! -n "$var" ]; then
echo "$var is empty"
exit 0
fi
# 判断两个变量是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 ne $var2'
fi
shell中条件判断if中的-a到-z的意思
运维 Rock 发表了文章 0 个评论 2042 次浏览 2017-02-15 18:03
[ -a FILE ] 如果 FILE 存在则为真。
[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 FILE 存在则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
[ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小不为0则为真。
[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2,or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
[ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。
[ -z STRING ] “STRING” 的长度为零则为真。
[ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。
[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.
数字判断
[ $count -gt "1"] 如果$count 大于1 为真
-gt 大于
-lt 小于
-ne 不等于
-eq 等于
-ge 大于等于
-le 小于等于
[ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。
[ STRING1 != STRING2 ] 如果字符串不相等则为真。
[ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。
[ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。
Shell下判断一个命令是否存的最好方法
运维 Rock 发表了文章 0 个评论 4824 次浏览 2017-02-15 15:22
通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。
1、which非SHELL的内置命令,用起来比内置命令的开销大,并且非内置命令会依赖平台的实现,不同平台的实现可能不同。
[root@node1 ~]# type scp从上面可以看出command为内置命令,而which非内置命令。
scp is /usr/bin/scp
[root@node1 ~]# type command
command is a shell builtin
[root@node1 ~]# type which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
2、很多系统的which并不设置退出时的返回值,即使要查找的命令不存在,which也返回0
[root@node1 ~]# which ls所以许多系统的which实现,都偷偷摸摸干了一些“不足为外人道也”的事情。
/usr/bin/ls
[root@node1 ~]# echo $?
0
[root@node1 ~]# which www
no www in /usr/bin /bin /usr/sbin /sbin /usr/local/bin /usr/local/bin /usr/local/sbin /usr/ccs/bin
[root@node1 ~]# echo $?
0
所以,不要用which,可以使用下面的方法:
$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
The following is a portable way to check whether a command exists in PATH and is executable:更精彩的分析参考:http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script
[ -x "$(command -v foo)" ]
Example:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
运维如何写出不耍流氓的Shell脚本
运维 小白菜 发表了文章 3 个评论 2834 次浏览 2016-12-02 22:33

声明
大家都是文明人,尤其是做运维的,那叫一个斯文啊。怎么能耍流氓呢?赶紧看看,编写 SHELL 脚本如何能够不耍流氓。
MySQL备份脚本案例
1、不记录日志的shell
脚本就是耍流氓!
我们经常在工作中会遇到一个苦恼的事情,一个 Shell 脚本到底干了什么,什么时候开始执行,什么时候结束的。尤其是数据库备份,我们想知道我们的 MySQL 数据库备份时间。所以给脚本加日志显得尤为重要。那么我们的脚本应该有一个日志的函数,专门用于记录日志:
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
shell_log "shell beginning, Write log test"
shell_log "shell success, Write log test"
上面的脚本我编写了一个日志函数shell_log,每次记录日志,我们直接执行shell_log把日志内容当作第一个参数传给它就可以了,赶紧试试。
[root@labs shell]# cat shell_template.sh.log
2016-08-27 06-01-19 : shell_template.sh :shell beginning ,write log test
2016-08-27 06-01-19 : shell_template.sh :shell success ,write log test
2、直接就能执行的Shell脚本很容易耍流氓
一个脚本直接就能执行?难道不是直接就能执行吗?试想,你临时编写了一个特别重要的脚本,干的事情可能有破坏性,一不小心被别人./执行了怎么办呢?而且很多时候我们一个脚本的功能可能有多个,所以我们有必要让用户可以选择进行执行。
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
# Shell Usage
shell_usage(){
echo $"Usage: $0 {backup}"
}
# Backup MySQL All Database with mysqldump or innobackupex
mysql_backup(){
shell_log "mysql backup start"
shell_log "mysql backup stop"
}
# Main Function
main(){
case $1 in
backup)
mysql_backup
;;
*)
shell_usage;
esac
}
#Exec
main $1
上面的脚本我们编写了shell_usage函数,用来告诉用户,这个脚本的使用方法。同时,我要强调一下,像编写Shell, 我们经常是面向过程的,建议以函数为单位,这样脚本非常的清晰可读。赶紧执行以下看看效果吧。
[root@labs shell]# ./shell_template.sh
Usage: ./shell_template.sh {backup}
3、不加锁的Shell脚本就是让别人耍流氓
你编写的脚本能多个人同时执行吗?如果不能,那么如果多个人一起执行会怎么样呢?想想是不是有点冒冷汗。所以,不要给我们的其它小伙伴留下陷阱。不过如果你公司就你一个运维,真的不用怕吗?试想如果是定时任务再运行这个脚本,上一次没有运行完毕,然后到时间又运行了?然后,然后,然后,后果好可怕。
#!/bin/bash
# Shell Env
SHELL_NAME="shell_template.sh"
SHELL_DIR="/opt/shell"
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
LOCK_FILE="/tmp/${SHELL_NAME}.lock"
#Write Log
shell_log(){
LOG_INFO=$1
echo "$(date "+%Y-%m-%d") $(date "+%H-%M-%S") : ${SHELL_NAME} : ${LOG_INFO}" >> ${SHELL_LOG}
}
# Shell Usage
shell_usage(){
echo $"Usage: $0 {backup}"
}
shell_lock(){
touch ${LOCK_FILE}
}
shell_unlock(){
rm -f ${LOCK_FILE}
}
# Backup MySQL All Database with mysqldump or innobackupex
mysql_backup(){
if [ -f "$LOCK_FILE" ];then
shell_log "${SHELL_NAME} is running"
echo "${SHELL_NAME}" is running && exit
fi
shell_log "mysql backup start"
shell_lock
sleep 10
shell_log "mysql backup stop"
shell_unlock
}
# Main Function
main(){
case $1 in
backup)
mysql_backup
;;
*)
shell_usage;
esac
}
#Exec
main $1
我为脚本增加了两个函数shell_lock和shell_unlock非常简单,就是创建一个锁文件。然后再执行的时候先判断锁文件是否存在,如果存在说明有其它用户在执行,就退出。如果没有自己创建锁文件,开始执行,执行完毕删除锁文件。
好的,现在你可以赶紧再开一个窗口试试能不能执行这个脚本,或者到/tmp目录下看看是否创建了锁文件。请注意:如果已知的异常退出,一定也要删除这个锁文件。
一般创建锁文件放到/var/lock/subsys/
目录下,比如postfix的锁文件就是:
prog="postfix"
lockfile=/var/lock/subsys/$prog
做好事须留名
对于一个功能脚本来说,貌似还少了点什么。对,就是注释!我们要说明白这个脚本是干啥的。或者以后你离职后,别人看到这个脚本之后,我擦,这么牛掰的脚本是谁写的呢?不要怕,写上你的大名。
#######################################################
# $Name: shell_template.sh
# $Version: v1.0
# $Function: Backup MySQL Databases Template Script
# $Author: Jason Zhao
# $organization: https://www.baidu.com
# $Create Date: 2016-08-27
# $Description: You know what i mean,hehe
#######################################################
当然还有很多编写脚本的技巧,没法一一描述,不过如果能掌握上面的三种技巧,立马感觉编写的脚本有点高大上,有木有?
常用Linux系统Debug命令
运维 Geek小A 发表了文章 0 个评论 2882 次浏览 2016-07-09 13:06
netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn
netstat -n | awk '/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}'
netstat -n | awk '/^tcp/ {++state[$NF]}; END {for(key in state) print key,"\t",state[key]}'
netstat -n | awk '/^tcp/ {++arr[$NF]};END {for(k in arr) print k,"\t",arr[k]}'
netstat -n |awk '/^tcp/ {print $NF}'|sort|uniq -c|sort -rn
netstat -ant | awk '{print $NF}' | grep -v '[a-z]' | sort | uniq -c
netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn
netstat -n | awk '/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}'
netstat -n | awk '/^tcp/ {++state[$NF]}; END {for(key in state) print key,"\t",state[key]}'
netstat -n | awk '/^tcp/ {++arr[$NF]};END {for(k in arr) print k,"\t",arr[k]}'
netstat -n |awk '/^tcp/ {print $NF}'|sort|uniq -c|sort -rn
netstat -ant | awk '{print $NF}' | grep -v '[a-z]' | sort | uniq -c
2、查找请求80端口最多的20个IP连接
netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -n20
netstat -ant |awk '/:80/{split($5,ip,":");++A[ip[1]]}END{for(i in A) print A,i}' |sort -rn|head -n20
tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |head -n 20
3、查找较多time_wait连接
netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20
4、找查较多的SYN连接
netstat -an | grep SYN | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | more
5、根据端口列进程
netstat -ntlp | grep 80 | awk '{print $7}' | cut -d/ -f1
6、获取Web访问前10位的ip地址
cat access.log|awk '{print $1}'|sort|uniq -c|sort -nr|head -n 10
cat access.log|awk '{counts[$(11)]+=1}; END {for(url in counts) print counts[url], url}'
7、访问次数最多的文件或页面,取前20
cat access.log|awk '{print $11}'|sort|uniq -c|sort -nr|head -n 20
8、列出传输最大的几个rar文件
cat access.log|awk '{print $11}'|sort|uniq -c|sort -nr|head -n 20
9、列出输出大于200000byte(约200kb)的rar文件以及对应文件发生次数
cat access.log |awk '($10 > 200000 && $7~/\.rar/){print $7}'|sort -n|uniq -c|sort -nr|head -n 100
10、如果日志最后一列记录的是页面文件传输时间,则有列出到客户端最耗时的页面
cat access.log |awk '($7~/\.php/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -n 100
cat access.log |awk '($7~/\.php/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -n 100
11、列出最最耗时的页面(超过60秒的)的以及对应页面发生次数
cat access.log |awk '($NF > 60 && $7~/\.php/){print $7}'|sort -n|uniq -c|sort -nr|head -n 100
12、列出传输时间超过 30 秒的文件
cat access.log |awk '($NF > 30){print $7}'|sort -n|uniq -c|sort -nr|head -n 20
13、统计网站流量(G)
cat access.log |awk '{sum+=$10} END {print sum/1024/1024/1024}'
14、统计404的连接
awk '($9 ~/404/)' access.log | awk '{print $9,$7}' | sort
15、统计http status
cat access.log |awk '{counts[$(9)]+=1}; END {for(code in counts) print code, counts[code]}'
cat access.log |awk '{print $9}'|sort|uniq -c|sort -rn
16、查看是哪些爬虫在抓取内容
tcpdump -i eth0 -l -s 0 -w - dst port 80 | strings | grep -i user-agent | grep -i -E 'bot|crawler|slurp|spider'
17、查看数据库执行的sql语句
tcpdump -i eth0 -s 0 -l -w - dst port 3306 | strings | egrep -i 'SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL'
18、按域统计流量
zcat squid_access.log.tar.gz| awk '{print $10,$7}' |awk 'BEGIN{FS="[ /]"}{trfc[$4]+=$1}END{for(domain in trfc){printf "%s\t%d\n",domain,trfc[domain]}}'
19、调试命令
strace -p pid
20、磁盘性能
iostat -x 1 10
解决Apache child pid 22404 exit signal Segmentation fault (11)错误
运维 Ansible 发表了文章 0 个评论 6271 次浏览 2016-07-07 22:31
[Wed Jul 07 11:36:03 2016] [notice] child pid 22404 exit signal Segmentation fault (11)
[Wed Jul 07 11:36:03 2016] [notice] child pid 22424 exit signal Segmentation fault (11)
[Wed Jul 07 11:36:03 2016] [notice] child pid 22404 exit signal Segmentation fault (11)
[Wed Jul 07 11:36:03 2016] [notice] child pid 22424 exit signal Segmentation fault (11)
为了解决这个问题,网上搜了几个方法都无法解决,然后网上有人说是Apache的一个bug,是内存问题,最后我只能写个脚本处理。
1、检查服务器
[root@uweb1 atom]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
[root@uweb1 atom]# uname -r
2.6.32-573.22.1.el6.x86_64
[root@uweb1 atom]# slabtop
Active / Total Objects (% used) : 262463 / 284128 (92.4%)
Active / Total Slabs (% used) : 18670 / 18670 (100.0%)
Active / Total Caches (% used) : 92 / 172 (53.5%)
Active / Total Size (% used) : 74471.91K / 77331.03K (96.3%)
Minimum / Average / Maximum Object : 0.02K / 0.27K / 4096.00K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
103452 103431 99% 0.10K 2796 37 11184K buffer_head
34000 33764 99% 0.98K 8500 4 34000K ext4_inode_cache
33240 33240 100% 0.19K 1662 20 6648K dentry
17024 16889 99% 0.03K 152 112 608K size-32
15323 7993 52% 0.05K 199 77 796K anon_vma_chain
13148 8203 62% 0.20K 692 19 2768K vm_area_struct
11151 9723 87% 0.06K 189 59 756K size-64
7616 7071 92% 0.55K 1088 7 4352K radix_tree_node
7261 7251 99% 0.07K 137 53 548K selinux_inode_security
6767 3720 54% 0.05K 101 67 404K anon_vma
6534 6527 99% 0.14K 242 27 968K sysfs_dir_cache
4404 4404 100% 0.58K 734 6 2936K inode_cache
3816 3767 98% 0.07K 72 53 288K Acpi-Operand
2580 1833 71% 0.12K 86 30 344K size-128
2400 1523 63% 0.25K 160 15 640K filp
2208 2199 99% 0.04K 24 92 96K Acpi-Namespace
2080 2008 96% 0.19K 104 20 416K size-192
1782 1782 100% 0.64K 297 6 1188K proc_inode_cache
756 744 98% 1.00K 189 4 756K size-1024
其实apache报[notice] child pid 1421 exit signal Segmentation fault (11),绝大部分是内存泄露的问题,网上的禁止proxy和cache模块,经过我试验没有效果,修改php内存也一样。
2、解决内存泄露脚本
#!/bin/bash
time=`date`
echo $time > /tmp/clear_cached.txt
echo "total/used/free/shared/buffers/cached" >> /tmp/clear_cached.txt
echo "Cleart Before" >> /tmp/clear_cached.txt
free -m|grep Mem: >> /tmp/clear_cached.txt
sync;
echo 2 > /proc/sys/vm/drop_caches;
echo 0 > /proc/sys/vm/drop_caches;
echo "Clear After" >> /tmp/clear_cached.txt
free -m|grep Mem: >> /tmp/clear_cached.txt
AWK计算操作实践笔记
运维 chris 发表了文章 0 个评论 2287 次浏览 2016-06-17 18:00
127809一、求和
16813
551646
18858
18977
29369
23563
56302
11823
20212
149427
146515
awk '{sum+=$1} END {print "Sum = ", sum}'
二、求平均
awk '{sum+=$1} END {print "Average = ", sum/NR}'如果有浮点的话还需要 .2%之类格式支持
三、求最大值
awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}'
四、求最小值(min的初始值设置一个超大数即可)
awk 'BEGIN {min = 2000000000} {if ($1
五、案例分析
部分原始数据如下:09:14:00.500 3279.20 5 3279.80 29 3279.80 73 28715第一步已经实现了对原始数据每分钟最大值、最小值、平均值的统计。我把第一次统计后的数据列出来:
09:15:00.500 3279.00 14 3279.80 9 3279.80 134 28723
09:15:01.0 3279.00 11 3279.20 24 3279.20 155 28721
09:15:01.500 3279.00 3 3279.20 15 3279.20 172 28715
09:15:02.0 3278.20 7 3278.80 7 3279.20 190 28719
09:15:02.500 3278.20 2 3278.60 1 3278.80 205 28721
09:15:03.0 3278.40 1 3278.60 25 3278.60 215 28727
09:15:03.500 3278.00 88 3278.60 13 3278.60 236 28729
09:15:04.0 3278.00 88 3278.40 12 3278.20 239 28728
09:15:04.500 3278.20 2 3278.40 12 3278.20 255 28724
09:15:05.0 3278.00 78 3278.20 1 3278.00 268 28724
09:15:05.500 3278.00 71 3278.40 10 3278.20 279 28726
09:15:06.0 3278.00 65 3278.20 14 3278.00 288 28726
09:15:06.500 3278.00 58 3278.20 16 3278.00 295 28722
09:15:07.0 3278.00 48 3278.20 5 3278.20 317 28728
09:15:07.500 3278.00 44 3278.40 8 3278.00 337 28733
09:15:08.0 3278.00 39 3278.40 8 3278.00 344 28727
09:15:08.500 3278.20 1 3278.40 7 3278.20 351 28729
09:15:09.0 3278.20 1 3278.40 5 3278.20 361 28726
09:15:09.500 3278.00 29 3278.40 4 3278.20 368 2872609:19 3297.80 3296.00 3296.8$1: 时间, $2: 分钟最大值, $3: 分钟最小值, $4: 分钟平均值
09:20 3299.00 3296.60 3297.8
09:21 3298.40 3296.20 3296.9
09:22 3299.80 3297.20 3298.4
09:23 3299.20 3296.20 3298.3
09:24 3299.00 3297.20 3298.1
以上数据通过如下方式实现的:#!/bin/sh说明:把以上数据做个累计最大值和累计最小值统计。
srcpath=./src/
despath=./des/
for file in $(ls -1 -F ${srcpath} | grep -v [/$]);do
# 第一步:处理原始数据
# 通过substr来截取时间字段的[小时:分钟]
# 处理后的数据格式为 time max min arg ;共4个字段
# 最后把统计后的数据保存至目标临时文件
# 使用了三元运算符
awk '{
time=substr($1,1,5)
count[time]++
max[time]=$6>max[time]?$6:max[time]
min[time]=(!length(min[time])||$6[time])?$6:min[time]
sum[time]+=$6
}
END{
for(i in count) {
print i,max,min,sum/count
}
}' ${srcpath}${file}|sort> ${despath}${file}_tmp
done
初始化统计的时候,累计最值和每分钟最值是一样的.
要求输出如下格式数据:09:19 3297.80 3296.00 3296.8 3297.80 3296.00
09:20 3299.00 3296.60 3297.8 3299.00 3296.00
09:21 3298.40 3296.20 3296.9 3299.00 3296.00
09:22 3299.80 3297.20 3298.4 3299.80 3296.00
09:23 3299.20 3296.20 3298.3 3299.80 3296.00
09:24 3299.00 3297.20 3298.1 3299.80 3296.00
Linux增加虚拟内存swap脚本
运维 being 发表了文章 0 个评论 3213 次浏览 2016-05-16 10:09
#!/bin/bash
#增加1G的swap空间
dd if=/dev/zero of=/swapfile bs=1MB count=1024
#制作一个swap文件
mkswap /swapfile
#启动swap分区
swapon /swapfile
#添加开机自启
echo '/swapfile none swap defaults 0 0' >> /etc/fstab
Shell中数学计算总结
运维 Ansible 发表了文章 1 个评论 2404 次浏览 2016-03-22 00:39
错误方法举例
A:
var=1+1B:
echo $var
输出的结果是1+1,悲剧,呵呵
var=1
var=$var+1
echo $var
输出结果是1+1,依然悲剧,呵呵
正确方法
A: 使用let
var=1注意:
let "var+=1"
echo $var
输出结果为2,这次没有悲剧
- []经我测试let几乎支持所有的运算符,在网上看到一篇文章说“let不支持++、--和逗号、(、)”,但经我测试自加、自减、以及括号的优先级都得到了很好的支持[/][]方幂运算应使用“”[/][]参数在表达式中直接访问,不必加$[/][]一般情况下算数表达式可以不加双引号,但是若表达式中有bash中的关键字则需加上[/][]let后的表达式只能进行整数运算[/]
B: 使用(())
var=1注意:
((var+=1))
echo $var
输出结果为2
(())的使用方法与let完全相同
C: 使用$[]
var=1注意:
var=$[$var+1]
echo $var
输出结果位2
- []$[]将中括号内的表达式作为数学运算先计算结果再输出[/][]对$[]中的变量进行访问时前面需要加$[/][]$[]支持的运算符与let相同,但也只支持整数运算[/]
D: 使用expr
var=1注意:
var=`expr $var + 1`
echo $var
输出结果为2
- []expr后的表达式个符号间需用空格隔开[/][]expr支持的操作符有: |、&、<、<=、=、!=、>=、>、+、-、、/、%[/*][]expr支持的操作符中所在使用时需用\进行转义的有:|、&、<、<=、>=、>、[/*][]expr同样只支持整数运算[/]
E:使用bc(可以进行浮点数计算)
var=1介绍:
var=`echo "$var+1"|bc`
echo $var
输出结果为2
bc是linux下的一个简单计算器,支持浮点数计算,在命令行下输入bc即进入计算器程序,而我们想在程序中直接进行浮点数计算时,利用一个简单的管道即可解决问题。注意:
- []经我测试bc支持除位操作运算符之外的所有运算符。[/][]bc中要使用scale进行精度设置[/]
浮点数计算实例:
var=3.14F:使用awk(可进行浮点数计算)
var=`echo "scale=2;$var*3"|bc`
echo $var
输出结果为9.42
var=1介绍:
var=`echo "$var 1"|awk '{printf("%g",$1*$2)}'`
echo $var
输出结果为2
awk是一种文本处理工具,同时也是一种程序设计语言,作为一种程序设计语言,awk支持多种运算,而我们可以利用awk来进行浮点数计算,和上面bc一样,通过一个简单的管道,我们便可在程序中直接调用awk进行浮点数计算。注意:
- []awk支持除微操作运算符之外的所有运算符[/][]awk内置有log、sqr、cos、sin等等函数[/]
浮点数计算实例:
var=3.14
var=`echo "$var 2"|awk '{printf("%g",sin($1/$2))}'`
echo $var
输出结果为1
总结
终于把所有搜集到的资料看完,最后总结分享给大家,以后再遇到shell计算问题,就可以直接用了!