Shell

Shell

Shell如何处理IP地址排序

运维 Nock 回复了问题 2 人关注 1 个回复 1222 次浏览 2022-11-11 09:06 来自相关话题

sed常用替换小技巧记录

运维 Something 发表了文章 0 个评论 1681 次浏览 2020-08-20 14:48 来自相关话题

1. 去掉行首空格 sed 's/^[ \t]*//g'2. 去掉行末空格 sed 's/[ \t]*$//g'3. 去掉所有空格 sed s/[[:space:]]//g4. 替换符号 sed "s/^\(.* ...查看全部
1. 去掉行首空格
sed 's/^[ \t]*//g'
2. 去掉行末空格
sed 's/[ \t]*$//g'
3. 去掉所有空格
sed s/[[:space:]]//g
4. 替换符号
sed "s/^\(.*\)$/'\1'/" 
sed "s/^\(.*\)$/aa =>\1/"

Shell中如何像Python一样利用pass关键字什么都不干

运维 空心菜 回复了问题 2 人关注 1 个回复 9851 次浏览 2019-04-11 16:23 来自相关话题

怎么给awk取到的列叫''引号

运维 空心菜 回复了问题 2 人关注 1 个回复 4396 次浏览 2017-09-26 17:29 来自相关话题

Shell脚本判断变量或者文件是否存在案例

运维 Rock 发表了文章 0 个评论 4488 次浏览 2017-02-22 14:50 来自相关话题

脚本代码1:#!/bin/bash # site: openskill.cn myPath="/data/logs" myFile="/data/logs/access.log" # ...查看全部
bash.jpg

脚本代码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 个评论 2257 次浏览 2017-02-15 18:03 来自相关话题

shell中条件判断if中的-a到-z的意思 [ -a FILE ] 如果 FILE 存在则为真。  [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。 [ -c FILE ] 如果 FIL ...查看全部
shell中条件判断if中的-a到-z的意思

[ -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 个评论 5304 次浏览 2017-02-15 15:22 来自相关话题

通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。 ...查看全部
command.jpg

通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。
 
1、which非SHELL的内置命令,用起来比内置命令的开销大,并且非内置命令会依赖平台的实现,不同平台的实现可能不同。
[root@node1 ~]# type scp
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'
从上面可以看出command为内置命令,而which非内置命令。
 
2、很多系统的which并不设置退出时的返回值,即使要查找的命令不存在,which也返回0
[root@node1 ~]# which ls
/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实现,都偷偷摸摸干了一些“不足为外人道也”的事情。
 
所以,不要用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:

[ -x "$(command -v foo)" ]

Example:

if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
更精彩的分析参考:http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script

运维如何写出不耍流氓的Shell脚本

运维 小白菜 发表了文章 3 个评论 3102 次浏览 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
#######################################################

当然还有很多编写脚本的技巧,没法一一描述,不过如果能掌握上面的三种技巧,立马感觉编写的脚本有点高大上,有木有?

分享个基于sendclound的邮件群发软件 大家提点意见

回复

运维 Nappywu 发起了问题 1 人关注 0 个回复 4152 次浏览 2016-11-25 15:51 来自相关话题

Shell终端输出字体颜色记录

回复

运维 Geek小A 发起了问题 1 人关注 0 个回复 4847 次浏览 2016-07-15 12:05 来自相关话题

条新动态, 点击查看
Ansible

Ansible 回答了问题 • 2015-10-28 11:03 • 2 个回复 不感兴趣

shell如何截取字符串中的数字

赞同来自:

# cat aa.txt 12345zynet 234game 7903checaht1、替换法 # sed 's///g' aa.txt 12345 234 79032、过滤匹配法 # grep -Eo '+' aa.txt 12345 234 790... 显示全部 »
# cat aa.txt 12345zynet 234game 7903checaht1、替换法 # sed 's///g' aa.txt 12345 234 79032、过滤匹配法 # grep -Eo '+' aa.txt 12345 234 7903

shell如何截取字符串中的数字

运维 push 回复了问题 3 人关注 2 个回复 6173 次浏览 2015-10-28 11:11 来自相关话题

Shell如何处理IP地址排序

回复

运维 Nock 回复了问题 2 人关注 1 个回复 1222 次浏览 2022-11-11 09:06 来自相关话题

Shell中如何像Python一样利用pass关键字什么都不干

回复

运维 空心菜 回复了问题 2 人关注 1 个回复 9851 次浏览 2019-04-11 16:23 来自相关话题

怎么给awk取到的列叫''引号

回复

运维 空心菜 回复了问题 2 人关注 1 个回复 4396 次浏览 2017-09-26 17:29 来自相关话题

分享个基于sendclound的邮件群发软件 大家提点意见

回复

运维 Nappywu 发起了问题 1 人关注 0 个回复 4152 次浏览 2016-11-25 15:51 来自相关话题

Shell终端输出字体颜色记录

回复

运维 Geek小A 发起了问题 1 人关注 0 个回复 4847 次浏览 2016-07-15 12:05 来自相关话题

文本每行加''引号和合并为一行并以逗号分隔

回复

运维 空心菜 回复了问题 2 人关注 1 个回复 3941 次浏览 2016-04-15 10:30 来自相关话题

shell如何截取字符串中的数字

回复

运维 push 回复了问题 3 人关注 2 个回复 6173 次浏览 2015-10-28 11:11 来自相关话题

sed常用替换小技巧记录

运维 Something 发表了文章 0 个评论 1681 次浏览 2020-08-20 14:48 来自相关话题

1. 去掉行首空格 sed 's/^[ \t]*//g'2. 去掉行末空格 sed 's/[ \t]*$//g'3. 去掉所有空格 sed s/[[:space:]]//g4. 替换符号 sed "s/^\(.* ...查看全部
1. 去掉行首空格
sed 's/^[ \t]*//g'
2. 去掉行末空格
sed 's/[ \t]*$//g'
3. 去掉所有空格
sed s/[[:space:]]//g
4. 替换符号
sed "s/^\(.*\)$/'\1'/" 
sed "s/^\(.*\)$/aa =>\1/"

Shell脚本判断变量或者文件是否存在案例

运维 Rock 发表了文章 0 个评论 4488 次浏览 2017-02-22 14:50 来自相关话题

脚本代码1:#!/bin/bash # site: openskill.cn myPath="/data/logs" myFile="/data/logs/access.log" # ...查看全部
bash.jpg

脚本代码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 个评论 2257 次浏览 2017-02-15 18:03 来自相关话题

shell中条件判断if中的-a到-z的意思 [ -a FILE ] 如果 FILE 存在则为真。  [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。 [ -c FILE ] 如果 FIL ...查看全部
shell中条件判断if中的-a到-z的意思

[ -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 个评论 5304 次浏览 2017-02-15 15:22 来自相关话题

通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。 ...查看全部
command.jpg

通常情况下,我们利用Shell脚本写一些服务启动脚本或者软件的初始化启动脚本的时候,经常会依赖一些外部的目录,比如Linux下解压zip压缩包你会依赖unzip命令等情况。那在shell下我们怎么判断一个命令是否存在呢,看完下面的分析你就了解了。
 
1、which非SHELL的内置命令,用起来比内置命令的开销大,并且非内置命令会依赖平台的实现,不同平台的实现可能不同。
[root@node1 ~]# type scp
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'
从上面可以看出command为内置命令,而which非内置命令。
 
2、很多系统的which并不设置退出时的返回值,即使要查找的命令不存在,which也返回0
[root@node1 ~]# which ls
/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实现,都偷偷摸摸干了一些“不足为外人道也”的事情。
 
所以,不要用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:

[ -x "$(command -v foo)" ]

Example:

if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
更精彩的分析参考:http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script

运维如何写出不耍流氓的Shell脚本

运维 小白菜 发表了文章 3 个评论 3102 次浏览 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 个评论 3157 次浏览 2016-07-09 13:06 来自相关话题

1、查看TCP连接状态netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn netstat -n | awk '/^tcp/ {++S[$NF]};END {for(a in S) print ...查看全部
1、查看TCP连接状态
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 个评论 6566 次浏览 2016-07-07 22:31 来自相关话题

新搭建的测试环境用的Apache/2.2.15,然后测试的时候,页面报502,最后查看Apache的log日志如下: [Wed Jul 07 11:36:03 2016] [notice] child pid 22404 exit signal S ...查看全部
新搭建的测试环境用的Apache/2.2.15,然后测试的时候,页面报502,最后查看Apache的log日志如下:
[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 个评论 2494 次浏览 2016-06-17 18:00 来自相关话题

有列纯数字的文本(在之前可以通过各种手段过滤出只有数字这一列),比如它代表的是网站在线数,内容如下:127809 16813 551646 18858 18977 29369 2 ...查看全部
有列纯数字的文本(在之前可以通过各种手段过滤出只有数字这一列),比如它代表的是网站在线数,内容如下:
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
	
	

Linux增加虚拟内存swap脚本

运维 being 发表了文章 0 个评论 3436 次浏览 2016-05-16 10:09 来自相关话题

#!/bin/bash #增加1G的swap空间 dd if=/dev/zero of=/swapfile bs=1MB count=1024 #制作一个swap文件 mkswap / ...查看全部
#!/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 个评论 2646 次浏览 2016-03-22 00:39 来自相关话题

Shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看看: 错误方法举例​ A: var=1+1 echo $var ...查看全部
Shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看看:


错误方法举例​


A:
 var=1+1
echo $var

输出的结果是1+1,悲剧,呵呵
B:
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.14
var=`echo "scale=2;$var*3"|bc`
echo $var

输出结果为9.42
F:使用awk(可进行浮点数计算)​
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计算问题,就可以直接用了!
Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。