xargs占位符

比如在log目录下有3个文件,文件名为a、b、c,现在需要改名,加上.bak。

[root@iZj6c5o8z3bqyepm9pw4xsZ log]# ll
总用量 0
-rw-r--r-- 1 root root 0 8月  23 09:46 a
-rw-r--r-- 1 root root 0 8月  23 09:46 b
-rw-r--r-- 1 root root 0 8月  23 09:46 c

通过-I参数指定一个占位符

[root@iZj6c5o8z3bqyepm9pw4xsZ log]# ls | xargs -I filename sh -c "mv filename filename.bak" 
[root@iZj6c5o8z3bqyepm9pw4xsZ log]# ll
总用量 0
-rw-r--r-- 1 root root 0 8月  23 09:46 a.bak
-rw-r--r-- 1 root root 0 8月  23 09:46 b.bak
-rw-r--r-- 1 root root 0 8月  23 09:46 c.bak

shell读取json字符串

下载地址:https://github.com/stedolan/jq/releases

# 放到/usr/local/bin下并改名方便命令调用

[root@rootop logs]# cd /usr/local/bin/
[root@rootop logs]# wget -c https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
[root@rootop logs]# mv jq-linux64 jq

# 格式化json串,格式化后是带颜色的,很方便阅读。注意后面是跟的 点 .

[root@rootop logs]# tail -f www.rootop.org.log | jq .
{
  "remote_addr": "66.249.75.44",
  "remote_user": "-",
  "time_local": "24/May/2019:16:08:05 +0800",
  "request": "GET /pages/category/serversafe/page/2 HTTP/1.1",
  "status": "200",
  "body_bytes_sent": "8852",
  "http_referer": "-",
  "user_agent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
}

# 获取某个key的值,注意key前面有个点:

[root@rootop logs]# tail -f www.rootop.org.log | jq .user_agent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"

# 比如要在shell脚本中调用json中的某个值:

ua=`cat json_file | jq .user_agent`
echo $ua
这样就可以调到user_agent的值了。

shell读取yaml配置文件的值

目的:在代码提交自动打包时,先检测application.yml中spring.profiles.active的值是否为test(加载测试环境配置文件),如果不是则取消打包。

PS:
当然也可以在jar包启动时通过命令指定测试环境配置文件

--spring.profiles.active=test

会覆盖代码中的值,命令行优先级高于代码中配置。

# 首先pip安装py中的一个包
$ pip install shyaml

windows安装后是个exe程序
linux安装后是python脚本

# a.yaml 示例

fx:
  url: http://192.168.10.16:8080/

# 获取url值:

$ cat a.yml | shyaml.exe get-value fx.url
http://192.168.10.16:8080/

这样配合其他脚本可以实现某些操作。

while read line语句中ssh远程执行命令,只运行了一次。

while read line语句中ssh远程执行命令,只运行了一次。
目的:批量修改主机信息。

有一个host.txt文件,记录服务器ip,已经配置好秘钥登陆。如:

[root@m ~]# cat host.txt
192.168.10.71
192.168.10.72
192.168.10.73

现在想批量修改主机名,比如idc-001、idc-002 …,后面3位是数字
# 通过 expr 表达式实现shell中进行数学运算
# 通过 printf 格式化字符串,不足3位用0补全

# 先拼接出来主机名,再进一步添加修改功能

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 n=`expr $n + 1`

done < host.txt

# 执行结果没问题

[root@m ~]# sh b
192.168.10.71 idc-001
192.168.10.72 idc-002
192.168.10.73 idc-003

# 下一步就要通过ssh登陆实现修改主机名

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -o "StrictHostKeyChecking no" root@$ip "echo $hostname > /etc/hostname && hostname $hostname"
 n=`expr $n + 1`

done < host.txt

# 运行

[root@m ~]# sh b
192.168.10.71 idc-001
[root@m ~]# 

就执行了一行,退出了。去看71这台机器是修改成功了,但是72、73仍旧没变化。怀疑问题出在ssh上。

原因:
ssh中有个参数为 -n 通过man看到解释:

 
Redirects stdin from /dev/null (actually, prevents reading from stdin).  This must be used when ssh is run in the background.  A common trick is to
use this to run X11 programs on a remote machine.  For example, ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the
X11 connection will be automatically forwarded over an encrypted channel.  The ssh program will be put in the background.  (This does not work if
ssh needs to ask for a password or passphrase; see also the -f option.)

即ssh从stdin中读取了while read line的内容,导致while语句没有输入了,就执行完了。
-n的作用就是阻止ssh读取标准输入,为了验证这个结论,修改下host.txt文件,并且把ssh要执行的命令去掉。

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -o "StrictHostKeyChecking no" root@$ip # 去掉了后面的命令
 n=`expr $n + 1`

done < host.txt
[root@m ~]# cat host.txt 最后两行为两条系统命令
192.168.10.71
uname -r
date

# 执行

[root@m ~]# sh b
192.168.10.71 idc-001
Pseudo-terminal will not be allocated because stdin is not a terminal.
3.10.0-514.el7.x86_64
Wed Apr 17 16:44:58 CST 2019

可以看到内核版本和日期,说明ssh从标准输入读取了内容做为命令执行了,导致while标准输入为空,最后退出。

# 修改后正确姿势,添加-n参数

#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -n -o "StrictHostKeyChecking no" root@$ip "hostname $hostname && echo $hostname > /etc/hostname"
 n=`expr $n + 1`

done < host.txt

# 执行结果

[root@m ~]# sh b
192.168.10.71 idc-001
192.168.10.72 idc-002
192.168.10.73 idc-003

再去看72、73两台机器正确修改了。

如何取得传入shell脚本的第i个值?要求i循环到几就取第几个参数

百度知道的一个问题,需求是:如何取得传入shell脚本的第i个值?要求i循环到几就取第几个参数。
开始想用shell下的$$i获取第几个参数,试了一下发现不行。
有点类似php下的$$var方式获取值。

<?php
$a = 'b';
$b = 2;
$c = $$a;
echo $c;

结果为 2

后来想出用数组方式,通过for循环,然后索引减1的方式获取。shell数组索引也是从0开始。

[root@machine1 ~]# cat a.sh 
#!/bin/bash
total=$#
array=($*)
for ((i=1;i<=$total;i++));
do
    echo "传递参数位:"$i
    echo "对应值:"${array[$i-1]}
done
[root@machine1 ~]# sh a.sh a b c d e
传递参数位:1
对应值:a
传递参数位:2
对应值:b
传递参数位:3
对应值:c
传递参数位:4
对应值:d
传递参数位:5
对应值:e

这样就实现了需求。