统计网络连接状态及数目查看进程号与所在目录统计进程打开的文件句柄数目查看打开某个端口的进程字符串截取时间戳匹配、过滤、替换awkgrepsed综合使用求和、求平均值过滤空白行for 循环的常用写法数值类型字符串类型shell 数组与字典shell 文件属性获取分割、合并大文件检查 IPv4 地址合法性检查进程是否重启nohup 后台启动 java 进程获取进程号、杀进程踢终端查询、启动、停止服务显示已经登录的用户、执行的命令添加定时任务at 定时任务crontab 定时任务watch 持续监视命令的执行情况TCP/UDP 收发数据、探测端口是否打开nctelnet逐行读取文件while 循环重定向法(管道法)文件描述符法for 循环如何解决 Linux Error: No space left on device判断磁盘空间是否满,inode 是否耗尽查找大文件查找访问某个目录的进程清空文件删除文件(少量)删除文件(大量)删除大文件查找指定范围内的日志信息tr 字符进行替换、压缩和删除生成密码生成不包含特殊字符密码生成自定义字符密码openssl 自签证书初始化 CA颁发证书NGINX 配置自签证书sudo 保存 vim 打开的文件拷贝并忽略特定的文件统计文件数目shell 实现多进程expect 自动登陆获取字符串的长度一键部署 zookeeper/kafka 集群部署集群配置信息添加自定义系统服务awk 转义单引号、双引号cp 拷贝同一个文件到多个目录cp 同时拷贝多个文件到同一个目录xxd 十六进制转换chattr 和 lsattr 保护文件md5sum 校验文件完整性获取子脚本的返回值查看有效配置项(行)批量设置文件、文件夹属性命令行设置取消代理查看代理保存所有登录用户的操作历史
xxxxxxxxxx# netstat 工具netstat -n|awk '/^tcp/ {++state[$NF]} END {for(i in state) print i, state[i]}'
# ss 工具(自动统计)ss -s
# 示例[root@localhost ~]# netstat -n|awk '/^tcp/ {++state[$NF]} END {for(i in state) print i, state[i]}'ESTABLISHED 1[root@localhost ~]# ss -sTotal: 425 (kernel 442)TCP: 8 (estab 1, closed 0, orphaned 0, synrecv 0, timewait 0/0), ports 3
Transport Total IP IPv6* 442 - - RAW 0 0 0 UDP 1 1 0 TCP 8 5 3 INET 9 6 3 FRAG 0 0 0xxxxxxxxxx[root@ ~]# pidof java25941 24975 24645 24258 24057 23569 23389 23278 16969 15711 14765 13091 12251 12104 8727
[root@izwz94pn5a866aolfw77rkz ~]# pwd 25941/root[root@izwz94pn5a866aolfw77rkz ~]# pwdx 2594125941: /opt/mall_service/ppmall-wallet/wallet-vle-service
[root@izwz94pn5a866aolfw77rkz ~]# pidof java|xargs pwdx 25941: /opt/mall_service/mall-wallet/wallet-usdt-service12251: /opt/mall_service/mall-gateway-server12104: /opt/mall_service/mall-user-server8727: /opt/mall_service/mall-asset-transferxxxxxxxxxxlsof -p PIDlsof -p PID|wc -lxxxxxxxxxx# 查看打开端口 80 的进程lsof -i :80
# 示例[root@localhost ~]# lsof -i :22COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsshd 2159 root 3u IPv4 14855 0t0 TCP *:ssh (LISTEN)sshd 2159 root 4u IPv6 14865 0t0 TCP *:ssh (LISTEN)sshd 2381 root 3r IPv4 15983 0t0 TCP localhost:ssh->192.168.2.1:61861 (ESTABLISHED)man bash 获取更全面的语法(在线手册)
xxxxxxxxxx# ${parameter#word} 最小限度从前面截取 word[root@localhost ~]# str="http://www.bigsillybear.com/index.html"[root@localhost ~]# echo ${str#*//}www.bigsillybear.com/index.html
# ${parameter##word} 最大限度从前面截取 word[root@localhost ~]# str="http://www.bigsillybear.com/index.html"[root@localhost ~]# echo ${str##*/} index.html
# ${parameter%word} 最小限度从后面截取 word[root@localhost ~]# str="http://www.bigsillybear.com/index.html"[root@localhost ~]# echo ${str%/*}http://www.bigsillybear.com
# ${parameter%%word} 最大限度从后面截取 word[root@localhost ~]# str="http://www.bigsillybear.com/index.html"[root@localhost ~]# echo ${str%%/*}http:
# ${parameter:offset} 从指定位置截取字# ${parameter:offset:length} 从指定位置截取指定长度[root@localhost ~]# str="http://www.bigsillybear.com/index.html"[root@localhost ~]# echo ${str:7}www.bigsillybear.com/index.html[root@localhost ~]# echo ${str:7:20} www.bigsillybear.com[root@localhost ~]# echo ${str:0-10} index.html[root@localhost ~]# echo ${str:0-10:5}indexxxxxxxxxxx# 获取当前时间戳[root@~ ]# date +%s1591582603
# 将时间戳转换为日期[root@~ ]# date -d @1591582603Mon Jun 8 10:16:43 CST 2020xxxxxxxxxx# 打印出从 1 到 10 之间的偶数seq 10|awk '{getline; print $0}'
# 打印出从 1 到 10 之前的奇数seq 10|awk '{print $0; getline}'
# 交换奇数、偶数行seq 10|awk '{getline tmp; print tmp; print $0}'
# 匹配指定行cat file|awk '/target/ {print $0}'Tips:
'*' 在 shell 中代表通配符,用来代表任意字符,但是在正则表达式中,其含义不同,代表有 0 个或多个某个字符('*' 前面指定的字符)。例如 oo* 表示第一个 o 一定存在,第二个 o 可以有一个或多个,也可以没有,因此代表至少一个 0
shell 中的反向选择为 [!range],正则里面为 [^range]
xxxxxxxxxx# 匹配指定行,并输出行号cat file|grep -n 'target'
# 未匹配上的所有行cat file|grep -v 'target'
# 匹配 tast 或者 testcat file|grep 't[ae]st'
# 行首、行尾关键词匹配cat file|grep '^key'cat file|grep 'key$'
# 匹配以小写字母开头的行cat file|grep '^[a-z]'
# 匹配不是以英文字母开头的行grep '^[^a-zA-Z]' file
# 匹配非空行cat file|grep -v '^$'
# grep 正则表达式中, '.' 代表任意一个字符,'*' 代表重复字符。# 匹配 g??d,例如 good,gabd,goxd ……cat file|grep 'g..d'
# 匹配两个 o 以上的字符串cat file|grep 'ooo*'
# 匹配以 g 开头和结尾,中间至少有一个 o 字符串cat file|grep 'goo*g'
# 匹配以 g 开头和结尾的字符串,'.*' 代表 0 个或多个任意字符cat file|grep 'g.*g'
# 匹配包含 2 个 o 的字符串的行cat file|grep 'o\{2\}'
# 匹配包含 2~5 个 o 的字符串的行grep -n 'o\{2,5\}' file
# 匹配包含 g 后面跟 2~3 个 o,再跟 d 的字符串的行[root@localhost ~]# cat filegooodgodgoodgooood[root@localhost ~]# grep -n 'go\{2,3\}d' file 1:goood3:good
# 匹配包含 g 后面跟 2 个以上 o,再跟 d 的字符串的行[root@localhost ~]# grep -n 'go\{2,\}d' file 1:goood3:good4:gooood
# 匹配多个条件,例如,去除空白行和以 '#' 开头的行cat file|grep -v '^$'|grep -v '^#'
# grep 扩展正则(grep -E 或 egrep)[root@localhost ~]# cat filegooodgodgoodgooood
# '+',匹配一个或多个重复字符[root@localhost ~]# cat file|grep -E 'goo+d'gooodgoodgooood
# '.',匹配 0 个或 1 个字符[root@localhost ~]# cat file|grep -E 'goo?d'godgood
# '|',匹配多个条件[root@localhost ~]# cat file|grep -E 'good|goood'gooodgood
# '()',将部分内容合成一个单元组,如下分别匹配 0 个或 1 个 oo,匹配一个或多个 oo[root@localhost ~]# cat file|grep -E 'g(oo)?d'good[root@localhost ~]# cat file|grep -E 'g(oo)+d'goodgooood
# 输出匹配行的上下行,如,匹配行的上 2 行,下 3 行[root@localhost ~]cat file|grep -B 2 -A 3 "target"it'sverytargetimportto tryhello[[:space:]] 表示空格或者 tab 的集合
xxxxxxxxxx# 替换文件中所有 \rsed -i 's/\r//g' file
# 删除所有空行sed -i '/^$/d' file
# 删除行首空格sed -i 's/^[ \t]*//g' file
# 删除行末空格sed -i 's/[ \t]*$//g' file
# 删除所有的空格sed -i 's/[[:space:]]//g' file
# 替换第 3~5 行中的 第 2 个 hello 为 worldsed -i '3,5s/hello/world/2' file# 替换所有的 hello 为 worldsed -i 's/hello/world/g'xxxxxxxxxx# 将当前目录下所有 env.conf 文件中 debug 替换为 releasefind . -name env.conf | xargs sed -i 's/debug/release/g'
# 将当前目录下所有满足条件的文件中 debug 替换为 releasels | xargs sed -i 's/debug/release/g'xxxxxxxxxxroot@0c1d475c709b:/# for((i=1;i<=3;++i)) do echo $i; done123root@0c1d475c709b:/# for((i=1;i<=3;++i)) do echo $i; done|awk '{sum+=$1} END {print "Sum = ", sum}'Sum = 6root@0c1d475c709b:/# for((i=1;i<=3;++i)) do echo $i; done|awk '{sum+=$1} END {print "Average = ", sum/NR}'Average = 2xxxxxxxxxx# 使用 grepgrep -v "^$" file
# 使用 trcat file|tr -s '\n'
# 使用 sedcat file|sed '/^$/d'
# 使用 awkcat file|awk '{if($0 != "") print $0}'cat file|awk '{if(length != 0) print $0}'xxxxxxxxxx# i = i*3+1for((i=1; i<=10; i++))do echo $(expr $i \*3 + 1)donexxxxxxxxxxfor i in $(seq 1 10)do echo $(expr $i \* 3 + 1);donexxxxxxxxxxfor i in {1..10}do echo $(expr $i \* 3 + 1);donexxxxxxxxxxawk 'BEGIN {for(i=1; i<=10; i++) print i}'xxxxxxxxxxfor i in `ls`do echo $idonexxxxxxxxxxfor i in $*do echo $idonexxxxxxxxxxfor i in f1 f2 f3do echo $idonexxxxxxxxxxlist="rootfs usr data"for i in $listdo echo $idonexxxxxxxxxx#/!/bin/bash
echo "shell 定义字典"declare -A dicdic=([key1]="value1" [key2]="value2" [key3]="value3")
# 打印指定 key 的 valueecho ${dic["key1"]}
# 打印所有key值echo ${!dic[*]}
# 打印所有valueecho ${dic[*]}
# 字典添加一个新元素dic+=([key4]="value4")
# 遍历key值for key in $(echo ${!dic[*]})do echo "$key, ${dic[$key]}"done
echo "shell 定义数组"list=("value1" "value2" "value3")
# 打印指定下标echo ${list[1]}
# 打印所有下标echo ${!list[*]}
# 打印数组下标echo ${list[*]}
# 数组增加一个元素list=("${list[@]}" "value3")
# 按序号遍历for i in "${!arr[@]}"; do echo "$i, ${arr[$i]}"done
#按数据遍历for v in ${ARR[*]}do echo $vdonexxxxxxxxxx-e (equal)-e filename, 判断文件是否存在 -d (directory)-d filename,判断文件是否为目录 -f (file)-f filename,判断文件是否为常规文件 -L (link)-L filename,判断文件是否问链接文件 -r (read)-r filename,判断文件是否可读 -w (write)-w filename,判断文件是否可写 -x (exec)-x filename,判断文件是否可执行 -s (size)-s filename,判断文件长度是否为0 -h (hard link)-h filename,判断文件是否为硬链接文件 -nt (newer than)filename1 -nt filename2,判断文件1是否比文件2新 -ot (older than)filename1 -ot filename2,判断文件1是否比文件2旧xxxxxxxxxx# 按照指定行数分割split -l 500 large_file.log new_file_prefix
# 按照文件大小分割split -b 100m large_file.log new_file_prefix
# 使用 cat 进行文件合并cat new_file_prefix* > large_file.logxxxxxxxxxxCheckIPAddr(){ # IP地址必须为全数字 echo $1|grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" > /dev/null
if [ $? -ne 0 ] then return 1 fi
ipaddr=$1 a=`echo $ipaddr | awk -F . '{print $1}'` # 以"."分隔,取出每个列的值 b=`echo $ipaddr | awk -F . '{print $2}'` c=`echo $ipaddr | awk -F . '{print $3}'` d=`echo $ipaddr | awk -F . '{print $4}'`
for num in $a $b $c $d do if [ $num -gt 255 ] || [ $num -lt 0 ]; then return 1 fi done
return 0}
# 调用CheckIPAddr 192.168.1.1
if [ $? -ne 0 ]; then echo "invalid"fixxxxxxxxxx
if [ $# -ne 1 ]; then echo "Usage: [Process Name]" exit 0fi
PID=`ps afx|grep $1|grep -v "grep"|grep -v "/bin/bash"|head -n 1|awk '{print $1}'`
while [ 1 ]do PID2=`ps afx|grep $1|grep -v "grep"|grep -v "/bin/bash"|head -n 1|awk '{print $1}'`
if [ $PID2 ]; then if [ ! $PID ]; then PID=$PID2 echo "PID: $PID" else if [ $PID -ne $PID2 ]; then echo "Server is reboot, PID: $PID --> $PID2" PID=$PID2 else echo "Server is running, PID: $PID2" fi fi else echo "Server is not running" fi
sleep 1donexxxxxxxxxxnohup java -classpath xxx_service_1.0.jar xxx_entry > xxx_service.log 2>&1 &xxxxxxxxxxps afx|grep 进程名|grep -v grep|awk '{print $1}'|xargs kill -9pgrep 进程名|xargs kill -9pidof 进程名|xargs kill -9pkill -9 进程名killall -9 进程名xxxxxxxxxx[root@ip-172-31-41-16 ~]# whoroot pts/0 2023-05-11 23:42 (113.118.147.45)root pts/1 2023-05-11 23:32 (113.118.147.45)[root@ip-172-31-41-16 ~]# w 23:42:38 up 43 days, 12:38, 2 users, load average: 0.12, 0.12, 0.16USER TTY LOGIN@ IDLE JCPU PCPU WHATroot pts/0 23:42 4.00s 0.02s 0.01s wroot pts/1 23:32 9:58 0.06s 0.02s tail -f nohup.out[root@ip-172-31-41-16 ~]# pkill -9 -t pts/0Connection to 1.1.1.1 closed.xxxxxxxxxx# 新管理方式,如 Cent OS >= 7.xsystemctl start/status/enable/disable/stop/restart xxx_service
# 旧管理方式,如 Cent OS < 7.xservice xxx_service start/status/stop/restartxxxxxxxxxx# 显示已经登录的用户以及正在执行的命令w
# 示例> w 18:27:34 up 89 days, 6:41, 6 users, load average: 0.46, 0.46, 0.34USER TTY FROM LOGIN@ IDLE JCPU PCPU WHATroot pts/1 172.13.30.133 14:30 3:56m 0.33s 0.33s -bashkevin pts/2 172.13.30.219 Thu08 19:14 3.06s 3.06s -bashkevin pts/5 172.13.30.219 17:48 0.00s 0.60s 0.01s wroot pts/6 172.13.30.219 18:09 17:10 0.04s 0.04s -bashkevin pts/7 172.13.30.219 18:06 20:42 0.00s 0.00s -bash
# 显示已经登录的用户、登录的终端who
# 示例> whoroot pts/1 2018-03-27 14:30 (172.13.30.133)kevin pts/2 2018-03-22 08:09 (172.13.30.219)root pts/3 2018-03-27 14:31 (172.13.30.133)kevin pts/5 2018-03-27 17:48 (172.13.30.219)root pts/6 2018-03-27 18:09 (172.13.30.219)kevin pts/7 2018-03-27 18:06 (172.13.30.219)xxxxxxxxxx# 示例:添加一个 1 分钟之后执行的任务,按 Ctrl + D 退出> at now +1 minutesat> echo hello > ~/at.logat> <EOT>job 6 at 2018-03-27 19:20
# 示例:查询所有 at 任务> atq6 2018-03-27 19:20 a kevin
# 示例:删除 at 定时任务(6 位 job ID)> atrm 6xxxxxxxxxx# 添加定时任务crontab -e
# 查询所有 crontab 任务crontab -l
# 示例# Example of job definition:# .---------------- minute (0 - 59)# | .------------- hour (0 - 23)# | | .---------- day of month (1 - 31)# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR# sun,mon,tue,wed,thu,fri,sat# | | | | |# * * * * * user-name command to be executed# 每个小时第 05 分执行同步系统时间、硬件时钟05 */1 * * * rdate -t 30 -s time.nist.gov && /usr/sbin/hwclock -wxxxxxxxxxx# 每隔 3s,打印一次指定端口 9999 处于连接已建立的连接数目watch -n 3 'netstat -anp|grep 9999|wc -l'xxxxxxxxxx# 监听 1234nc -l 1234
# 连接 1234nc 127.0.0.1 1234xxxxxxxxxxtelnet 127.0.0.1 1234xxxxxxxxxxwhile read LINEdo echo $LINEdone < $FILExxxxxxxxxxcat $FILE|while read LINEdo echo $LINEdonexxxxxxxxxx# 如下两个操作可合并# exec 3<&0 exec 0<$FILEexec 3<&0exec 0<$FILE
while read LINEdo echo $LINEdone
exec 0<&3xxxxxxxxxxfor LINE in `cat $FILE`do echo $LINEdonexxxxxxxxxxdf -hdf -ixxxxxxxxxx# 按照大小降序排列(取出前 10 个大文件)du -sh target.dir|sort -n|head
# 查找目录下大于 1M 且小于 10M 的文件find target.dir -size +1M -size -10M -type f -name "*.jpg"
# 指定查询目录层级du -h --max-depth=1xxxxxxxxxxlsof +d /tmp
# 示例> lsof +d ~/Blog/COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEbash 6936 kevin cwd DIR 253,2 4096 3675368 /home/kevin/Blogvim 24969 kevin cwd DIR 253,2 4096 3675368 /home/kevin/Blogvim 24969 kevin 4u REG 253,2 20480 3675605 /home/kevin/Blog/.SHELL.md.swpx
cat /dev/null > target.file
# 批量清空文件find /data/java -name *.out | xargs -I {} sh -c 'cat /dev/null > "{}"'
# 执行 truncate 文件的内容被清空,但文件的 inode 仍然存在,因此文件占用的磁盘空间不会被立刻释放,当文件被删除才会被真正释放truncate -s 0 target.filex
find /tmp -type f -exec rm {} \;
# 注意:xargs 默认是以空白字符(空格,TAB,换行符)来分割记录的,如果文件名中间有空格,例如 /tmp/file 1.log,# 此时自动被当做两个文件 /tmp/file 与 1.log,执行命令报错:No such file or directoryfind -name '*.log' -print0|xargs -0 rm
# 可能存在大小为 0 字节的空文件,同样也会占用 inodefind /tmp -type f -size 0 -exec rm {} \;xxxxxxxxxx# 先建立一个空目录mkdir /data/blank
# 用 rsync 删除目标目录rsync --delete-before -d /data/blank/ /tmp/xxxxxxxxxxcat /dev/null > target.filexxxxxxxxxx# 查找时间范围 2018/03/28 05:00:00 ~ 2018/03/28 07:59:59 的所有日志sed -n '#2018/03/28 05:[0-9][0-9]:[0-9][0-9]#,#2018/03/28 07:[0-9][0-9]:[0-9][0-9]#p' log
# 查找 2018-03-29 00:24:00 ~ 2018-03-29 00:25:59 的所有日志cat log|grep -E '2018-03-29 00:2[4-5]:[0-9][0-9]'xxxxxxxxxx# 将输入字符由大写转换为小写> echo "Hello World"|tr 'a-z' 'A-Z'HELLO WORLD
# 删除字符> echo "hello 123 world 456"|tr -d '0-9'hello world
# 将制表符转换为空格cat file|tr '\t' ' '
# 将不在指定字符集合中的所有字符删除> echo "aa.,a 1 b#$bb 2 c*/cc 3 ddd 4"|tr -d -c '0-9 \n'1 2 3 4
# 去掉重复的字符> echo "hell oooo wwwworld"|tr -d ' ow'hello world
# 数字相加操作> seq 100|xargs -n1|echo $[ $(tr '\n' '+')0 ]5050
# 取出 mac 地址,去掉冒号,转换为大写> echo "2018/03/29 16:00:22 bc:ec:29:39:d4:2f online"|awk -F ' ' '{print $3}'|tr 'a-z' 'A-Z'|tr -d ':'BCEC2939D42Fxxxxxxxxxx# cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -10hstFP2uG9y要配置密码的长度,请将 cut 命令中的数字更改为所需的长度,例如 24 个字符
xxxxxxxxxx# cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -30LNFDZBoDVSdBDVc21OHVQ2pwYIEB5g不想混淆 0 或 O,1 或 l ?用另一个过滤掉 tr
xxxxxxxxxx# cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' | tr -d '0O1l'|cut -c -30MHoUrT5GvbStxCdABSzxWUxLDACRbNxxxxxxxxxx# cat password.sh
n=$1
set="abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-="rand=""for i in `seq 1 $n`; do char=${set:$RANDOM % ${#set}:1} rand+=$chardoneecho $randxxxxxxxxxx# bash password.sh 30q*&2*2XKMZIxet3fcUFWMgDFS!C-@jdownload: 自签证书
xxxxxxxxxx
# name: init_ca.sh# author: kevin
echo ""echo -e "\e[1;33m===============================================\e[0m"echo -e "\e[1;33mFunction: construct your own private CA.\e[0m"echo -e "\e[1;33mSupported OS: CentOS 6.8\e[0m"echo -e "\e[1;33m===============================================\e[0m"echo ""
# check root permissionif [ $UID -ne 0 ]; then echo -e "\e[1;31m[Failed] superuser privileges are required\e[0m" exit 1else echo -e "\e[1;32m[Passed] superuser privileges meeted\e[0m"fi
if [ -e /etc/pki/CA/cacert.pem ]; then echo -e -n "\e[1;31m[WARN] re-init CA? (Y/n)\e[0m" while [ 1 ] do read Confirm if [ "$Confirm"x = "Y"x -o "$Confirm"x = "y"x ]; then echo -e "\e[1;33m[INFO] start to re-init CA\e[0m" break; elif [ "$Confirm"x = "n"x ]; then exit 1 else echo -e -n "\e[1;31m[ERROR] invalid option, re-init CA? (Y/n)\e[0m" continue fi donefi
OS=`cat /etc/redhat-release | awk '{print $1 " " $3}'`SupportedOS="CentOS 6.8"if [ "$OS"x = "$SupportedOS"x ]; then echo -e "\e[1;32m[Passed] OS: $OS\e[0m"else echo -e "\e[1;31m[Failed] $SupportedOS supported only\e[0m" exit 1;fi
# install opensslFound=`openssl version | grep "command not found"`if [ -n $Found ]; then echo -e "\e[1;33m[INFO] openssl installed\e[0m"else echo -e "\e[1;33m[INFO] install openssl\e[0m" yum install openssl -y > /dev/nullfi
echo -e "\e[1;33m[INFO] generate CA's private key\e[0m"(umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 2048)
echo -e "\e[1;33m[INFO] generate CACert\e[0m"cat > gen_cert.exp << EOF
set timeout 30
spawn openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out \/etc/pki/CA/cacert.pem -days 3655
expect { "Country Name (2 letter code)" { send "cn\r"; exp_continue }
"State or Province Name (full name)" { send "Guang Dong\r"; exp_continue }
"Locality Name (eg, city)" { send "Shen Zhen\r"; exp_continue }
"Organization Name (eg, company)" { send "XXX Tech Ltd.\r"; exp_continue }
"Organizational Unit Name (eg, section)" { send "XXX's CA\r"; exp_continue }
"Common Name (eg, your name or your server's hostname)" { send "xxx.cn\r"; exp_continue }
"Email Address" { send "cloud@xxx.cn\r"; exp_continue }}EOF
chmod +x gen_cert.exp./gen_cert.exprm -rf gen_cert.exp
echo -e "\e[1;33m[INFO] CACert's information in detail:\e[0m"openssl x509 -noout -text -in /etc/pki/CA/cacert.pem
echo -e "\e[1;33m[INFO] Verify CACert's invalidism\e[0m"openssl verify /etc/pki/CA/cacert.pem
echo -e "\e[1;33m[INFO] init CA's serial\e[0m"touch /etc/pki/CA/{index.txt,serial}echo 01 > /etc/pki/CA/serial
echo -e "\e[1;33m[INFO] Congratulations! Everything is done.\e[0m"xxxxxxxxxx
# name: gen_cert.sh# author: kevin
# check root permissionvalidate_superuser() { if [ $UID -ne 0 ]; then echo -e "\e[1;31m[Failed] superuser privileges are required\e[0m" exit 1 else echo -e "\e[1;32m[Passed] superuser privileges meeted\e[0m" fi}
usage() { echo -e "\e[1;31mUsage: $0 <organization> <number>\e[0m" echo -e "\e[1;33mOption:\e[0m" echo -e "\e[1;33m Organization for example, Gateway or Access\e[0m" echo -e "\e[1;33m number [1, 9999] number of certification(s) \generated in batch\e[0m"}
introduction() { echo "" echo -e "\e[1;33m====================================================\e[0m" echo -e "\e[1;33mFunction: Issue Certification.\e[0m" echo -e "\e[1;33mSupported OS: CentOS 6.8\e[0m" echo -e "\e[1;33m====================================================\e[0m" echo ""}
if [ $# -ne 2 ]; then usage exit 1else echo $2|grep "^[1-9][0-9]\{0,3\}$" > /dev/null
if [ $? -ne 0 ]; then usage echo -e "\e[1;31m[ERROR] ARGUMENT INVALID\e[0m" exit 1 fifi
validate_superuser
introduction
if [ -e /etc/pki/CA/cacert.pem ]; then echo -e "\e[1;33m[INFO] start to issue certification\e[0m"else exit 1fi
OS=`cat /etc/redhat-release | awk '{print $1 " " $3}'`SupportedOS="CentOS 6.8"if [ "$OS"x = "$SupportedOS"x ]; then echo -e "\e[1;32m[Passed] OS: $OS\e[0m"else echo -e "\e[1;31m[Failed] $SupportedOS supported only\e[0m" exit 1;fi
# install opensslFound=`openssl version | grep "command not found"`if [ -n $Found ]; then echo -e "\e[1;33m[INFO] openssl installed\e[0m"else echo -e "\e[1;33m[INFO] install openssl\e[0m" yum install openssl -y > /dev/nullfi
mkdir -p certrm -rf cert/*
for ((count=1; count <= $2; ++ count))doecho -e "\e[1;33m[INFO] generate $1's private key\e[0m"(umask 077;openssl genrsa -out ./cert/$1\.key 2048)
echo -e "\e[1;33m[INFO] generate $1's Cert\e[0m"cat /etc/pki/CA/index.txt >> /etc/pki/CA/index.txt.bakcat /dev/null > /etc/pki/CA/index.txt
cat > gen_cert.exp << EOF
set timeout 30
spawn openssl req -new -key ./cert/$1\.key -out ./cert/$1\.csr
expect { "Country Name (2 letter code)" { send "cn\r"; exp_continue }
"State or Province Name (full name)" { send "Guang Dong\r"; exp_continue }
"Locality Name (eg, city)" { send "Shen Zhen\r"; exp_continue }
"Organization Name (eg, company)" { send "xxx Tech Ltd.\r"; exp_continue }
"Organizational Unit Name (eg, section)" { send "$1\r"; exp_continue }
"Common Name (eg, your name or your server's hostname)" { send "xxx.cn\r"; exp_continue }
"Email Address" { send "cloud@xxx.cn\r"; exp_continue }
"A challenge password" { send "xxx666!\r"; exp_continue }
"An optional company name" { send "XXX Tech Ltd.\r"; exp_continue }}EOF
chmod +x gen_cert.exp./gen_cert.exp
# sign certificationcat > sign_cert.exp << EOF
set timeout 30
spawn openssl ca -in ./cert/$1\.csr -out ./cert/$1\.crt -days 3655
expect { "Sign the certificate" { send "y\r"; exp_continue }
"1 out of 1 certificate requests certified, commit" { send "y\r"; exp_continue }}EOF
chmod +x sign_cert.exp./sign_cert.exp
(umask 077;touch ./cert/$1\.pem)cat ./cert/$1\.crt >> ./cert/$1\.pemcat ./cert/$1\.key >> ./cert/$1\.pemopenssl rsa -in ./cert/$1\.pem -pubout -out ./cert/$1\.pub
# renamecd cert > /dev/nullrm -rf $1\.csrfor file in `ls $1\.*`do mv $file `echo "$count-$file" `donecd - > /dev/nulldone
rm -rf gen_cert.exprm -rf sign_cert.exp
echo -e "\e[1;33m[INFO] Total: $2 certification(s).\e[0m"echo -e "\e[1;33m[INFO] Output Directory: ./cert\e[0m"echo -e "\e[1;33m[INFO] Congratulations! Everything is done.\e[0m"xxxxxxxxxxcd /etc/nginx# 生成服务器端私钥openssl genrsa -out server.key 1024# 生产服务器端公钥openssl rsa -in server.key -pubout -out server.pem# 生成 CA 私钥openssl genrsa -out ca.key 1024# Common Name 填写域名或 localhost 或项目代称openssl req -new -key ca.key -out ca.csr# 生成 CA 证书openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt# 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件openssl req -new -key server.key -out server.csr# 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt# 使用 openssl 进行转换openssl x509 -in server.crt -out server.cer -outform der将 server.crt 和 server.key 拷贝到 NGINX 的配置文件即可
xxxxxxxxxx# 方法一:w !sudo sh -c "cat >'%'"# 方法二:w !sudo tee "%"xxxxxxxxxxcp `ls|grep -v dummy.txt|xargs` target_dirxxxxxxxxxx# 统计普通文件数目,不包括隐藏文件(即,以'.'开头的文件)ls -l|grep "^-"|wc -lfind . -maxdepth 1 -type f|grep -v "\./\."|wc -l
# 统计普通文件数目,包括隐藏文件ls -al|grep "^"|wc -lfind . -maxdepth 1 -type f|wc -l
# 统计目录数目ls -l|grep "^d"|wc -lfind . -maxdepth 1 -type f|grep -v "\./\."|wc -lxxxxxxxxxx# 命令加'&'后台运行cmd1 &cmd2 &# ...cmdN &# 必须加上,否则脚本执行完毕导致所以进程被结束waitxxxxxxxxxx
# 脚本运行参数:ip、root 用户密码
set ip [lindex $argv 0]set password [lindex $argv 1]set timeout 30000
spawn ssh root@$ipexpect { "*yes/no" { send "yes\r"; exp_continue } "*password:" { send "$password\r" }}
expect "*#"
# 在目标机器执行任何命令,例如 echosend "echo hello\r"expect "*#"
# 退出send "exit\r"expect eofxxxxxxxxxx# 利用${#str}来获取字符串的长度[root@localhost ~]# str="hello"[root@localhost ~]# echo ${#str}5
# 利用 awk 的 length 方法来获取字符串的长度[root@localhost ~]# echo hello|awk '{print length($0)}'5
# 利用 awk 的 NF 项来获取字符串的长度[root@localhost ~]# echo hello|awk -F '' '{print NF}'5
# 利用 wc -L 来获取字符串的长度,详见 man wc[root@localhost ~]# echo hello|wc -L5
# 利用 wc -c 来获取字符串的长度[root@localhost ~]# echo hello|wc -c6# -n: 不统计换行符[root@localhost ~]# echo -n hello|wc -c 5
# 利用 expr 的 length 方法来获取字符串的长度[root@localhost ~]# str=hello[root@localhost ~]# expr length ${str}5
# 利用 expr 的 $str : ".*" 来获取字符串的长度# 备注:.* 代表任意字符,即,用任意字符来匹配字符串 hello,结果能够匹配 5 个[root@localhost ~]# str="hello"; expr $str : ".*"5功能:部署 zookeeper/kafka 集群
说明:
需要提前规划好 zookeeper/kafka 集群,并配置好 basic.info,详见 basic.info。
可以支持 zookeeper/kafka 单机或集群部署 单机部署,配置信息参考 basic_example_standalone.info 集群部署,配置信息参考 basic_example_cluster.info
使用步骤:
修改 install_zk_kafka.tar.gz 中 install_zookeeper.sh/install_kafka 中安装包的路径(建议从内网下载安装包,可搭建 ftp 或 http 服务器),重新生成 install_zk_kafka.tar.gz
将步骤 1 中生成的压缩包上传到 ftp 或 http 服务器
将 zk_kafka_deploy.tar.gz 拷贝到操作机器(操作机器能够访问集群中所有机器即可)
解压,修改 zk_kafka_deploy.sh 中 install_zk_kafka.tar.gz 的路径
修改集群配置信息 basic.info
执行脚本 ./zk_kafka_deploy.sh
download:
xxxxxxxxxx
# name: zk_kafka_deploy.sh# author: kevin
# check root permissionif [ $UID -ne 0 ]; then echo "Superuser privileges are required to run this script." echo "e.g. \"sudo $0\"" exit 1fi
zookeepers=`cat basic.info | grep zookeeper`zookeepers=`echo ${zookeepers#*=}`
kafkas=`cat basic.info | grep kafka`kafkas=`echo ${kafkas#*=}`
password=`cat basic.info | grep cluster_common_passwd`password=`echo ${password#*=}`
zookeeper_array=($zookeepers)kafka_array=($kafkas)zookeeper_num=${#zookeeper_array[@]}kafka_num=${#kafka_array[@]}
# 校验 IP 是否有效CheckIPAddr(){ # IP地址必须为全数字 echo $1|grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" > /dev/null
if [ $? -ne 0 ] then return 1 fi
ipaddr=$1 a=`echo $ipaddr | awk -F . '{print $1}'` # 以"."分隔,取出每个列的值 b=`echo $ipaddr | awk -F . '{print $2}'` c=`echo $ipaddr | awk -F . '{print $3}'` d=`echo $ipaddr | awk -F . '{print $4}'`
for num in $a $b $c $d do if [ $num -gt 255 ] || [ $num -lt 0 ]; then return 1 fi done
return 0}
if [ $zookeeper_num -eq 0 -o $kafka_num -eq 0 ]; then echo "ERROR: cluster info invalid" exit 1;fi
for zk in $zookeepersdo CheckIPAddr $zk
if [ $? -ne 0 ]; then echo "ERROR: ip addr [$zk] invalid" exit 1; fidone
for kafka in $kafkasdo CheckIPAddr $kafka
if [ $? -ne 0 ]; then echo "ERROR: ip addr [$kafka] invalid" exit 1; fidone
cat > gen_rsa_pub.exp << EOF
set ip [lindex \$argv 0]set password [lindex \$argv 1]set timeout 30
spawn ssh root@\$ipexpect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
expect "*#"
send "yum install expect -y\r"expect "*#"
send "curl -O ftp://192.168.2.2/pub/install_zk_kafka.tar.gz\r"expect "*#"
send "tar -xzvf install_zk_kafka.tar.gz\r"expect "*#"
send "cd install_zk_kafka\r"expect "*#"
send "./gen_rsa_pub.sh\r"expect "*#"
send "cd ~\r"expect "*#"
send "rm -rf install_zk_kafka*\r"expect "*#"
send "exit\r"expect eofEOF
cat > scp_rsa_pub.exp << EOF
set ip [lindex \$argv 0]set password [lindex \$argv 1]set timeout 30
spawn scp root@\$ip:~/.ssh/id_rsa.pub .expect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
send "exit\r"expect eofEOF
cat > write_rsa_pubs.exp << EOF
set ip [lindex \$argv 0]set password [lindex \$argv 1]set timeout 30
spawn scp zk_id_rsa.pub root@\$ip:~expect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
send "exit\r"expect eof
spawn ssh root@\$ipexpect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
expect "*#"send "cat ~/zk_id_rsa.pub >> ~/.ssh/authorized_keys\r"
expect "*#"send "rm -rf ~/zk_id_rsa.pub\r"
expect "*#"send "exit\r"
expect eofEOF
if [ $zookeeper_num -gt 1 ]; then cat /dev/null > zk_id_rsa.pub chmod +x gen_rsa_pub.exp chmod +x scp_rsa_pub.exp chmod +x write_rsa_pubs.exp
for zk in $zookeepers do ./gen_rsa_pub.exp $zk $password ./scp_rsa_pub.exp $zk $password cat id_rsa.pub >> zk_id_rsa.pub rm -rf id_rsa.pub done
for zk in $zookeepers do ./write_rsa_pubs.exp $zk $password done
rm -rf zk_id_rsa.pubfi
rm -rf gen_rsa_pub.exp rm -rf scp_rsa_pub.exp rm -rf write_rsa_pubs.exp
cat > install_zookeeper.exp << EOF
set ip [lindex \$argv 0]set password [lindex \$argv 1]set zookeepers [lindex \$argv 2]set id [lindex \$argv 3]set timeout 600
spawn ssh root@\$ipexpect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
expect "*#"
send "curl -O ftp://192.168.2.2/pub/install_zk_kafka.tar.gz\r"expect "*#"
send "tar -xzvf install_zk_kafka.tar.gz\r"expect "*#"
send "cd install_zk_kafka\r"expect "*#"
send "./install_zookeeper.sh \$zookeepers \$id\r"expect "*#"
send "cd ~\r"expect "*#"
send "rm -rf install_zk_kafka*\r"expect "*#"
send "exit\r"expect eofEOF
chmod +x install_zookeeper.exp
id=0for zk in $zookeepersdo # in order to avoid info expired when the machine is rebuild sed -i "/$ip/d" ~/.ssh/known_hosts >/dev/null 2>&1
./install_zookeeper.exp $zk $password "'$zookeepers'" $id id=`expr $id + 1`done
rm -rf install_zookeeper.exp
zookeeper_connect=""for zk in $zookeepersdo zookeeper_connect=${zookeeper_connect}${zk}":2181,"donezookeeper_connect=${zookeeper_connect%,*}
cat > install_kafka.exp << EOF
set ip [lindex \$argv 0]set password [lindex \$argv 1]set broker_id [lindex \$argv 2]set zookeeper_connect [lindex \$argv 3]set timeout 600
spawn ssh root@\$ipexpect { "*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "\$password\r" }}
expect "*#"
send "curl -O ftp://192.168.2.2/pub/install_zk_kafka.tar.gz\r"expect "*#"
send "tar -xzvf install_zk_kafka.tar.gz\r"expect "*#"
send "cd install_zk_kafka\r"expect "*#"
send "./install_kafka.sh \$broker_id \$ip \$zookeeper_connect\r"expect "*#"
send "cd ~\r"expect "*#"
send "rm -rf install_zk_kafka*\r"expect "*#"
send "exit\r"expect eofEOF
chmod +x install_kafka.exp
id=0for kafka in $kafkasdo # in order to avoid info expired when the machine is rebuild sed -i "/$ip/d" ~/.ssh/known_hosts >/dev/null 2>&1
./install_kafka.exp $kafka $password $id $zookeeper_connect id=`expr $id + 1`done
rm -rf install_kafka.exp
echo $?xxxxxxxxxx# 此文件只能修改 value,不能修改 key# 即,只能修改等号右边的值,根据实际集群信息修改zookeeper=192.168.2.3 192.168.2.4 192.168.2.5kafka=192.168.2.3 192.168.2.4 192.168.2.5cluster_common_passwd=123456备注:源码编译安装 Apache Tomcat 之后,可以将其添加到系统服务(此方法仅适用于 CentOS 7 之前版本)
进入 /etc/ini.d 文件夹,新建文件 tomcat
xxxxxxxxxx# 2345是要设为要启动的运行级别,10启动优先级,90杀死进程的优先级# chkconfig: 2345 10 90 # description: script to start/stop tomcat service # by dudebing99 2014-10-28
source /etc/profile
case $1 in
#start service start) sh /usr/share/apache-tomcat-7.0.56/bin/startup.sh echo "" ;;
#stop service stop) sh /usr/share/apache-tomcat-7.0.56/bin/shutdown.sh echo "" ;;
#restart service restart) sh /usr/share/apache-tomcat-7.0.56/bin/shutdown.sh echo "" #status status) var=$(ps -ef | grep tomcat | grep -v "grep" | wc -l) if [[ $var -eq 4 ]] ; then echo -e "\nTomcat is running.\n" else echo -e "\nTomcat is stopped.\n" fi ;;#help help) echo -e "\nUsage:start|stop|restart|status\n";;
#other *) echo -e "\nUnexpected command, tips as follows.\n" echo -e "Usage:start|stop|restart|status\n" ;;
esac 更改文件权限
xxxxxxxxxxchmod 755 /etc/init.d/tomcat添加服务
xxxxxxxxxxchkconfig --add tomcat确认服务是否已开启
xxxxxxxxxxchkconfig tomcat --listxxxxxxxxxx# 转义双引号,直接使用 \" 即可[kevin@www mass]$ cat aaa 1 Q. Ngai2 T. Hoa3 T. Ninh4 D. Nai[kevin@www mass]$ cat aaa |awk '{print "{id: "$1", name: \"" $2" "$3"\"}"}'{id: 1, name: "Q. Ngai"}{id: 2, name: "T. Hoa"}{id: 3, name: "T. Ninh"}{id: 4, name: "D. Nai"}
# 转义单引号,使用 '\''[kevin@www mass]$ cat aaa 1 Q. Ngai2 T. Hoa3 T. Ninh4 D. Nai[kevin@www mass]$ cat aaa |awk '{print "{id: "$1", name: '\''" $2" "$3"'\''}"}'{id: 1, name: 'Q. Ngai'}{id: 2, name: 'T. Hoa'}{id: 3, name: 'T. Ninh'}{id: 4, name: 'D. Nai'}xxxxxxxxxx# 拷贝 dummy.txt 到目录 /tmp/1 和 /tmp/2# -n 1 每次传递 1 个参数给 xargsecho /tmp/1 /tmp/2|xargs -n 1 cp dummy.txt拷贝多个文件
xxxxxxxxxx[root@localhost ~]# ls /tmp/dummy/ file1 file2 file3 file5[root@localhost ~]# cp /tmp/dummy/{file1,file5} destdir/[root@localhost ~]# ls destdir/file1 file5文件名有共同前缀
xxxxxxxxxx[root@localhost ~]# ls destdir/ [root@localhost ~]# ls /tmp/dummy/file1 file2 file3 file5[root@localhost ~]# cp /tmp/dummy/file{1..3} destdir/[root@localhost ~]# ls destdir/file1 file2 file3xxxxxxxxxxkevin@ubuntu:~$ echo "hello world"|xxd -ps68656c6c6f20776f726c640akevin@ubuntu:~$ echo "hello world"|xxd -ps -u68656C6C6F20776F726C640A通常,可以通过
chattr +i实现对文件的保护
xxxxxxxxxxroot@iZbp18qlevqaoff8jmlpx7Z:~# lsattr stack.log -------------e-- stack.log# 通过 chattr +i 给文件添加 "i" 属性,文件将不能被删除、改名、设定连结也无法写入或新增数据root@iZbp18qlevqaoff8jmlpx7Z:~# chattr +i stack.log root@iZbp18qlevqaoff8jmlpx7Z:~# lsattr stack.log ----i--------e-- stack.log# 写入数据出错root@iZbp18qlevqaoff8jmlpx7Z:~# echo "a" >> stack.log-bash: stack.log: Permission denied# 去掉 "i" 属性root@iZbp18qlevqaoff8jmlpx7Z:~# chattr -i stack.logroot@iZbp18qlevqaoff8jmlpx7Z:~# echo "a" >> stack.logxxxxxxxxxx# 生成 md5sumroot@iZwz9b1eyn1aqqy0s3qbadZ:~/paychain# md5sum coind91cc995a9406262bc70794c00042e69e coind
# 将 md5sum 写入文件root@iZwz9b1eyn1aqqy0s3qbadZ:~/paychain# md5sum coind > coind.md5root@iZwz9b1eyn1aqqy0s3qbadZ:~/paychain# cat coind.md5 91cc995a9406262bc70794c00042e69e coind
# 校验文件完整性,OK 即为完整root@iZwz9b1eyn1aqqy0s3qbadZ:~/paychain# md5sum -c coind.md5 coind: OKxxxxxxxxxx# cat ./a.sh
i=99exit $ixxxxxxxxxx# cat ./a.sh
i=99exit $ixxxxxxxxxx# ./b.shret: 99xxxxxxxxxx$ grep -v "^#" /path/to/config/file如果要去掉空行
xxxxxxxxxxegrep -v "^#|^$" /path/to/config/file对所有的文件夹设置755,所有的文件设置644
xxxxxxxxxxfind . -exec sh -c 'if [[ -d "{}" ]]; then chmod 755 "{}"; else chmod 644 "{}"; fi ' \;或
xxxxxxxxxxfind ./ -type d -print|xargs chmod 755find ./ -type f -print |xargs chmod 644xxxxxxxxxx$ vim ~/.zshrc# proxyproxy () { export http_proxy="http://127.0.0.1:8080" export https_proxy=$http_proxy export socks5_proxy="socks5://127.0.0.1:8080" echo "HTTP Proxy on"}
# noproxynoproxy () { unset http_proxy unset https_proxy unset socks5_proxy echo "HTTP Proxy off"}
$ source ~/.zshrcgit 代理
xxxxxxxxxx# 查看代理git config --global http.proxygit config --global https.proxy# 取消代理git config --global --unset http.proxygit config --global --unset https.proxy命令行代理
xxxxxxxxxx# 查看代理env|grep -i proxy# 取消代理unset http_proxyunset https_proxyxxxxxxxxxxUSER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`if [ "$USER_IP" = "" ]thenUSER_IP=`hostname`fiif [ ! -d /tmp/dbasky ]thenmkdir /tmp/dbaskychmod 777 /tmp/dbaskyfiif [ ! -d /tmp/dbasky/${LOGNAME} ]thenmkdir /tmp/dbasky/${LOGNAME}chmod 300 /tmp/dbasky/${LOGNAME}fiexport HISTSIZE=40960DT=`date "+%Y-%m-%d_%H-%M-%S"`export HISTFILE="/tmp/dbasky/${LOGNAME}/${USER_IP}-dbasky.$DT"export HISTTIMEFORMAT="%F %T "chmod 600 /tmp/dbasky/${LOGNAME}/*dbasky* 2>/dev/null