【问题标题】:SSH for loop executing command scriptSSH for循环执行命令脚本
【发布时间】:2017-05-11 14:13:14
【问题描述】:

我有一个脚本可以从多个服务器获取服务器运行状况,如下所示:

#!/bin/bash
for ip
do
    ssh 192.168.1.209 ssh root@$ip cat /proc/loadavg | awk '{print $1}' #CPU Usage
    free | grep Mem | awk '{print $3/$2 * 100.0}' #Memory Usage
    df -khP  | awk '{print $3 "/" $2}' | awk 'FNR == 2' #Disk Space
    df -kihP  | awk '{print $3 "/" $2}' | awk 'FNR == 2' #Inode Space
    date +'%d %b %Y %r %Z' #Datetime
    ps -eo user,pid,pcpu,pmem,args|sort -nr -k3|head -5 #Process
done

209 在我的网络上就像一个门户,所以我必须首先通过 ssh 连接到它才能访问其他服务器。通过在终端上输入以下命令:

./my_script.sh 192.168.1.210 192.168.1.211 192.168.1.212

我想从每个服务器获取每个命令输出(ps、date 等)。 2 个服务器的预期输出应该是这样的:

0.11 #health from server 1
4.82577
1.7G/49G
46K/49M
27 Dec 2016 05:34:57 PM HKT
root        93  0.0  0.0 [kauditd]
root         9  0.0  0.0 [rcuob/0]
root      8740  0.0  0.0 ifstat --scan=100
root       829  0.0  0.0 /usr/sbin/wpa_supplicant -u -f /var/log/wpa_supplicant.log -c /etc/wpa_supplicant/wpa_supplicant.conf -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
0.00  #health from server 2
4.82422
1.7G/49G
46K/49M
27 Dec 2016 05:34:57 PM HKT
root        93  0.0  0.0 [kauditd]
root         9  0.0  0.0 [rcuob/0]
root      8740  0.0  0.0 ifstat --scan=100
root       829  0.0  0.0 /usr/sbin/wpa_supplicant -u -f /var/log/wpa_supplicant.log -c /etc/wpa_supplicant/wpa_supplicant.conf -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid

我面临的问题是它似乎只从一台服务器获取健康信息。这是为什么?是因为我不能像这样进行 SSH 吗?我正在使用 PHP exec() 函数来执行脚本 btw,以进一步格式化并将其显示在我的本地页面上。

【问题讨论】:

  • 哦,我忘了说,209 就像我网络上的一个门户。我只能从 209 ssh 到 210,211 等。所以我实际上是先 ssh 到 209
  • 我该怎么做?我已经给出了我所有的代码

标签: php bash shell ssh scripting


【解决方案1】:

好吧,我会做一些完全不同的事情。

首先我会编写一个commandlist.sh 脚本如下(不要忘记让它可执行...):

#!/bin/bash
echo "# Health from $(hostname)"
cat /proc/loadavg | cut -d' ' -f1 #CPU Usage
free | grep Mem | awk '{print $3/$2 * 100.0}' #Memory Usage
df -khP  | awk 'FNR == 2 {print $3 "/" $2}' #Disk Space
df -kihP  | awk 'FNR == 2 {print $3 "/" $2}' #Inode Space
date +'%d %b %Y %r %Z' #Datetime
ps -eo user,pid,pcpu,pmem,args|sort -nr -k3|head -5 #Process

(嗯.. 我会用非常不同的代码产生相同的输出,但由于这是你的脚本,我只编辑了几个多余的 awk 调用。)

然后,我会把它放在 209 上,在那里我还会安装 GNU parallel。 另外,我将~/.parallel/sshloginfile文件写成如下:

1/192.168.1.210
1/192.168.1.211
1/192.168.1.212

然后我会运行命令

ssh 192.168.0.209 parallel -S .. --nonall --bf commandlist.sh ./commandlist.sh

请仔细查看man parallel 以获得更多可能性。

【讨论】:

    【解决方案2】:

    bash 中执行此操作的最佳方法是使用Here Documents << 并在传递给脚本的每个参数($@)上运行一个循环

    for ip in "$@"
    do
        ssh 192.168.1.209 ssh root@"$ip" <<-EOF
        cat /proc/loadavg | awk '{print $1}'
        free | grep Mem | awk '{print $3/$2 * 100.0}' 
        df -khP  | awk '{print $3 "/" $2}' | awk 'FNR == 2'
        df -kihP  | awk '{print $3 "/" $2}' | awk 'FNR == 2'
        date +'%d %b %Y %r %Z'
        ps -eo user,pid,pcpu,pmem,args|sort -nr -k3|head -5
        EOF
    done
    

    记住NOT在标题&lt;&lt;-EOF和最后的EOF之前有前导或尾随空格,使用制表符空格作为终止EOF

    你现在可以运行脚本了

    ./my_script.sh 192.168.1.210 192.168.1.211 192.168.1.212     
    

    您还可以将脚本的内容包装在一个简单的bash 脚本中,然后一次性运行它

    #!/bin/bash
    
    cat /proc/loadavg | awk '{print $1}'
    free | grep Mem | awk '{print $3/$2 * 100.0}' 
    df -khP  | awk '{print $3 "/" $2}' | awk 'FNR == 2'
    df -kihP  | awk '{print $3 "/" $2}' | awk 'FNR == 2'
    date +'%d %b %Y %r %Z'
    ps -eo user,pid,pcpu,pmem,args|sort -nr -k3|head -5
    

    将上述脚本调用为commandlist.sh,并在for循环中调用它

    ssh 192.168.1.209 ssh root@"$ip" 'bash -s ' < /path-to/commandlist.sh
    

    【讨论】:

    • 我收到 ./health.sh: 第 14 行:警告:第 4 行的此处文档由文件结尾分隔(需要 `EOF')./health.sh: 第 15 行:语法错误:文件意外结束
    • 还是一样,顺便说一句“
    • @LimSY:同样对于done之前的终止令牌EOF,不要使用&lt;space&gt;字符,使用&lt;tab&gt;,你可以尝试一次吗?
    • 现在它没有任何错误,但没有任何输出。我必须按 ctrl+c 才能取消
    • @LimSY:你能试试我回答中的最后一个建议吗?将命令放在一个文件中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多