bash - 使用命令行参数(主机名)到 运行 外部命令

bash - using a command line argument (hostname) to run an external command

第一次post,如有遗漏请见谅

我有一个应该与 icinga 一起使用的脚本。我需要 icinga 来登录我的 Linux 框和 运行 像“script”这样的命令。该脚本然后将 运行 向该主机名发出命令,如 sudo /etc/init.d/apache2 status 然后报告“运行ning or unused”和退出状态 0 或 2。 我想知道如何添加另一个命令并根据给定的主机名使用一个或另一个 运行 。其中一半需要 apache2 运行ning,另一半需要一个名为 dss 的进程 运行ning。我宁愿没有两个单独的脚本。这是工作脚本,抱歉,它很草率,但我还没有做任何清理工作,我还不是很擅长 bash。

所以用户会 运行 脚本 ./chkdss2 或

#!/bin/bash
ec=0
ec1=2
var3=run
var4=unused

for host in "$@"
do
  var1=`ssh $host sudo /etc/init.d/dss status|awk '{print }'`
  var2="$( echo $var1 | cut -c 3-5 )"
if [[ "$var2" == "$var3" ]]; then
    echo "$host is running"
    echo $ec
  else
    echo "$host is not running"
    echo $ec1
fi
done

有几种方法可以测试特定主机名是用于 apache 还是 dss。您只需要为每种情况提供一个主机名列表,并检查收到的主机名是否包含在所述列表中。

方法一:使用数组

#!/bin/bash

# Method 1, using array lists of hosts
apachehosts=('ap1' 'ap2' 'ap3')
dsshosts=('dss1' 'dss2' 'dss3')

for host in "$@"
do
    if printf '%s\n' "${apachehosts[@]}" | grep -Fxq "$host"
    then
        echo "$host: APACHE HOST"
    elif printf '%s\n' "${dsshosts[@]}" | grep -Fxq "$host"
    then
        echo "$host: DSS HOST"
    else
        echo "ERROR, $host: unknown host"
    fi
done

要修改主机列表,只需添加或删除数组声明中的值 apachehostsdsshosts


方法二:使用case

#!/bin/bash

# Method 2, using case
for host in "$@"
do
    case "$host" in
        'ap1'|'ap2'|'ap3')
            echo "CASE, $host: APACHE HOST"
            ;;
        'dss1'|'dss2'|'dss3')
            echo "CASE, $host: DSS HOST"
            ;;
        *)
            echo "ERROR CASE, $host: unknown host"
            ;;
    esac
done

在这里,您可以编辑每种情况下的模式。


方法三: 使用 if

#!/bin/bash

# Method 3, using if
for host in "$@"
do
    if [[ "$host" == 'ap1' || "$host" == 'ap2' || "$host" == 'ap3' ]]
    then
        echo "IF, $host: APACHE HOST"
    elif [[ "$host" == 'dss1' || "$host" == 'dss2' || "$host" == 'dss3' ]]
    then
        echo "IF, $host: DSS HOST"
    else
        echo "IF, $host: unknown host"
    fi
done

此处修改if条件。我更喜欢其他方法,因为这个编辑起来比较复杂,不太清楚,尤其是当你的主机列表很长的时候。


方法 4:主机名条件

如果幸运的话,您的主机名有一些模式。前任。所有 apache 服务器都以字母 ap 开头,所有 dss 服务器的名称中都包含 dss,...

然后您可以简单地使用 2 个 if 语句来决定哪个是哪个。

#!/bin/bash

# Method 4, patterns
for host in "$@"
do
    if [[ $(echo "$host" | grep -c -e "^ap") -ne 0 ]]
    then
        echo "PATTERNS, $host: APACHE HOST"
    elif [[ $(echo "$host" | grep -c -e "dss") -ne 0 ]]
    then
        echo "PATTERNS, $host: DSS host"
    else
        echo "PATTERNS, $host: unknown host"
    fi
done

注意: 主机名apdss1 会在这里作为Apache 服务器出现。以前的方法会响应“未知主机”。您的模式必须足够严格以避免不匹配。

我有一个类似的任务,使用单个 ssh 请求获得很少的报告项目。

我必须在单个 ssh 命令中检索:

  1. 完整主机名 (FQDN)
  2. Linux版本
  3. 其 Docker 主机的 IP 地址(如果存在)或“none”

我的脚本分 3 个阶段运行。

1。从远程主机获取多行信息

ssh -q dudi-HP-Compaq-Elite-8300-MT  <<< '
date +%F:%T   # line 1: time stamp
hostname -f     # line 2: hostname 
awk  "/DESCR/{print $3}" /etc/lsb-release # line 3 : host linux distribution version
ip a | awk "/inet / && !/127.0.0.1/{sub(\"/.*\",\"\",$2);printf(\"%s \", $2)}"      # line 4: list IP address to the host
'

结果:

2022-03-05:22:22:21
dudi-HP-Compaq-Elite-8300-MT
20
192.168.2.111 192.168.122.1 172.17.0.1

2。处理来自远程主机的多行信息

从远程主机读取信息行,放入数组sshResultsArr

readarray -t sshResultsArr < <(ssh -q dudi-HP-Compaq-Elite-8300-MT  <<< '
date +%F:%T   # line 1: time stamp
hostname -f     # line 2: hostname 
awk  "/DESCR/{print $3}" /etc/lsb-release # line 3 : host linux distribution version
ip a | awk "/inet / && !/127.0.0.1/{sub(\"/.*\",\"\",$2);printf(\"%s \", $2)}"      # line 4: list IP address to the host
')
hostname=${sshResultsArr[1]}
osVersion=${sshResultsArr[2]}
hasDockerIp=$(grep -Eo "172(.[[:digit:]]{1,3}){3}" <<< "${sshResultsArr[3]}") # find IP starting with 172
hasDockerIp=${hasDockerIp:="none"} # if not found IP set to "NONE"

printf "%s \t OS version: %s \t has Docker IP: %s\n" "$hostname" "$osVersion" "$hasDockerIp"

结果:

dudi-HP-Compaq-Elite-8300-MT     OS version: 20          has Docker IP: 172.17.0.1

3。循环处理每个远程主机

#!/bin/bash
for host in "$@"; do
  readarray -t sshResultsArr < <(ssh -q $host  <<< '
  date +%F:%T   # line 1: time stamp
  hostname -f     # line 2: hostname 
  awk  "/DESCR/{print $3}" /etc/lsb-release # line 3 : host linux distribution version
  ip a | awk "/inet / && !/127.0.0.1/{sub(\"/.*\",\"\",$2);printf(\"%s \", $2)}"      # line 4: list IP address to the host
  ')
  hostname=${sshResultsArr[1]}
  osVersion=${sshResultsArr[2]}
  hasDockerIp=$(grep -Eo "172(.[[:digit:]]{1,3}){3}" <<< "${sshResultsArr[3]}") # find IP starting with 172
  hasDockerIp=${hasDockerIp:="none"} # if not found IP set to "NONE"

  printf "%s \t OS version: %s \t has Docker IP: %s\n" "$hostname" "$osVersion" "$hasDockerIp"
done

我能够从我收到的答案中汲取一些东西,并将一些效果很好的东西放在一起。谢谢大家的回答。

for host in "$@"
do
    case "$host" in
       ('vho1uc1-primary'|'vho1uc2-backup'|'vho2uc1-primary'|'vho2uc2-backup'|'vho3uc1-primary'|'vho3uc2-backup'|'vho10uc1-primary')
          var1=`ssh "$host" sudo /etc/init.d/apache2 status|awk '{print }'`
          var2="$( echo $var1 | cut -c 3-5 )"
            if [[ "$var2" == "$var3" ]]; then
          echo "Apache2 on $host is running"
          echo "0"
            else
          echo "Apache2 on $host is not running"
          echo "2"
          fi
          ;;
       *)
    esac
done