iptables delete some rules form a chain

以下两条命令均可用

iptables -t nat -L PREROUTING --line-numbers | grep RULE_NAME | cut -d" " -f 1 | xargs iptables -t nat -D PREROUTING

for i in $(iptables -t nat -nvL PREROUTING --line-numbers | grep RULE_NAME | grep ^[0-9] | awk '{ print $1 }' | tac); do iptables -t nat -D PREROUTING $i; done

How to run a crontab job every X seconds

如果你有一个job, 需要每隔5秒运行一次.

以下写法是错误的

* * * * * sleep 5; /bin/cmd

如果使用这种写法, 会导致在每分钟的第0秒开始, sleep 5秒以后, 再运行/bin/cmd, 然尔运行完就结束了, 不会每隔5秒运行一次.

正确写法1

* * * * * for i in {1..12}; do /bin/cmd; sleep 5; done

正确写法2

* * * * * REMAIN=60 INC=5 ; while ; do /bin/cmd; sleep $INC; REMAIN=$(($REMAIN - $INC)); done

正确写法3

* * * * * /bin/cmd
* * * * * sleep 5; /bin/cmd
* * * * * sleep 10; /bin/cmd
* * * * * sleep 15; /bin/cmd
......
* * * * * sleep 55; /bin/cmd

可以使用systemctl status cron.service -l命令看看cron服务的状态以及最新日志.

参考: How to run a cronjob every X seconds in cron

Linux get DevName of a directory

Linux系统下, 获得某一个子目录(例如/data/home/release )对应的DevName(如sdb等). 现在的情况是

有些机器是这样的

Filesystem      Size  Used Avail Use% Mounted on
......
/dev/sda5       1.6T  343G  1.2T  23% /data

而有些机器是这样的

Filesystem      Size  Used Avail Use% Mounted on
......
/dev/sda5       1.6T  343G  1.2T  23% /data
/dev/sdb        488M   56M  408M  12% /data/home/release

解决办法

part=`df -P /data/home/release | awk 'END{print $1}'`    #得到一个诸如/dev/sda3的字符串
devname=${part:5:3}             #切割上面的字符串,从第5位开始,取3位
echo $devname

Linux详细查看进程启动时间

Linux系统下查看进程启动时间和运行时间的命令

ps -o lstart -p PID         #根据PID来查询

ps -o lstart,etime -p PID   #根据PID来查询,打印出启动时间和已经运行的时间

ps -eO lstart | grep PROCESS    #根据进程名字查询

提示:
1, 大写的O表示preloaded,小写的o表示user-defined,e表示all processes
2, 如果查出来的时间是1-16:15:58, 则表示该运程运行了1天16小时15分钟
3, etime表示elapsed time, 即程序已经运行的时间

以下几个例子

$ ps -o lstart,etime -p 13062    #根据PID打印出启动时间和持续时间
                 STARTED     ELAPSED
Thu Sep 21 09:41:40 2017  1-01:50:35

$ ps -eo pid,lstart,cmd    #打印出所有进程(-e)的PID,启动时间
3428 Mon Nov  6 20:55:20 2017 /sbin/udevd -d
3495 Mon Nov  6 20:55:22 2017 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
3508 Mon Nov  6 20:55:22 2017 /usr/sbin/nscd
3532 Mon Nov  6 20:55:29 2017 /usr/sbin/snmpd -LS 2 d -Lf /dev/null -p /var/run/snmpd.pid -a
3548 Mon Nov  6 20:55:29 2017 /usr/sbin/sshd
3557 Mon Nov  6 20:55:29 2017 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g
3568 Mon Nov  6 20:55:29 2017 crond


#依次打印出某进程的pid,uid,user,启动时间,持续时间,占用CPU时间(cputime),以及cmd
$ ps -eo pid,euid,euser,lstart,etime,cputime,cmd | grep searcher_server
 7259  7259 Fri Sep 22 11:36:21 2017       00:01 S pts/0    00:00:00 grep 13062
13062 13062 Thu Sep 21 09:41:40 2017  1-01:54:42 S ?        1-15:50:04 /export/App/jd_search/searcher/server/bin/searcher_server

阿里云/京东云等进行端口转发

假设我们有个应用建立在国外的某个服务器上(如8.8.8.8:443端口上),现在希望使用阿里云/京东云等作为跳板来转发一下这个端口

开启端口转发

vim /etc/sysctl.conf
将 net.ipv4.ip_forward=0
修改成 net.ipv4.ip_forward=1

编辑后使用命令让配置马上生效
sysctl -p

相同端口的转发(将阿里云的443端口转发到8.8.8.8的443端口)

iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 8.8.8.8
iptables -t nat -A PREROUTING -p udp --dport 443 -j DNAT --to-destination 8.8.8.8

iptables -t nat -A POSTROUTING -p udp -d 8.8.8.8 --dport 443 -j SNAT --to-source 192.168.0.3
iptables -t nat -A POSTROUTING -p tcp -d 8.8.8.8 --dport 443 -j SNAT --to-source 192.168.0.3

请注意:一般来说,阿里云/京东云有个内网IP和公网IP,我们假设这里的192.168.0.3是阿里云/京东云的内网IP,这里不能写公网IP

不同端口的转发(将阿里云的5270端口转发到8.8.8.8的443端口)

iptables -t nat -A PREROUTING -p udp --dport 5270 -j DNAT --to-destination 8.8.8.8:443
iptables -t nat -A PREROUTING -p udp --dport 5270 -j DNAT --to-destination 8.8.8.8:443

iptables -t nat -A POSTROUTING -p udp -d 8.8.8.8 --dport 443 -j SNAT --to-source 192.168.0.3
iptables -t nat -A POSTROUTING -p tcp -d 8.8.8.8 --dport 443 -j SNAT --to-source 192.168.0.3

Shell将换行符换成空格(sed)

Shell将换行符换成空格的办法,用sed和tr均可实现。

sed命令

cat country.txt | sed ':label;N;s/\n/ /;b label'

tr命令

cat country.txt | tr "\n" " "

把tab换成换行符

cat country.txt | sed 's/\t/\n/g'

awk 'BEGIN { OFS = "\n" } { $1=$1; print }' input.txt > output.txt

tr '\t' '\n' < input.txt > output.txt

参考文章:
Convert a tab-delimited file to use newlines
sed命令替换换行符

运维实例:批量替换配置文件+批量重启服务

工作中遇到的一个小问题,记录一下。假设有一千台机器运行着nginx但每台机器上的nginx目录可能不太一样,比如
/export/servers/openresty-local/nginx/
/export/servers/openresty/nginx/
/export/servers/openresty-ngx-ump/nginx/
现在要替换掉nginx目录下的某个脚本,并且重启这个nginx服务。需要用到的工具有Ansbile和自己写的批量替换脚本batch_op.py

#准备远程机器列表
$ vim ip_list
10.191.172.201
10.190.143.38
10.187.110.4
10.190.49.237
10.190.198.192
10.190.163.211
#准备替换脚本
$ vim /tmp/b.sh
#!/bin/bash

if [ $(id -u) != "0" ]; then
    echo "Error: need root to run this script."
    exit 1
fi

a=`ps -ef | grep openresty | grep -v grep | awk '{ print $11 }' | cut -d\/ -f1,2,3,4`

if [ ! $a ]; then
    echo 'Error! Not found $a directory.'
elif [ -f $a/lualib/resty/nginx_diviner.lua ]; then
   cp $a/lualib/resty/nginx_diviner.lua $a/lualib/resty/nginx_diviner.lua.bak.`date +%Y%m%d%H%M%S` && \
   wget -q -O $a/lualib/resty/nginx_diviner.lua http://172.22.193.65:8003/nginx_diviner.lua && \
   chown admin:admin $a/lualib/resty/nginx_diviner.lua* && \
   $a/nginx/sbin/nginx -s reload && \
   echo "Found and replaced $a/lualib/resty/nginx_diviner.lua"
else
   echo "Not Found $a/lualib/resty/nginx_diviner.lua"
   exit 1
fi

if [ "$a" != "/export/servers/openresty" ] && [ -f /export/servers/openresty/lualib/resty/nginx_diviner.lua ]; then
   cp /export/servers/openresty/lualib/resty/nginx_diviner.lua /export/servers/openresty/lualib/resty/nginx_diviner.lua.bak.`date +%Y%m%d%H%M%S` && \
   wget -q -O /export/servers/openresty/lualib/resty/nginx_diviner.lua http://172.22.193.65:8003/nginx_diviner.lua && \
   chown admin:admin /export/servers/openresty/lualib/resty/nginx_diviner.lua && \
   echo "Extra Operation! also found and replaced /export/servers/openresty/lualib/resty/nginx_diviner.lua"
fi

继续阅读