Bash getopts 通过 SSH 远程运行命令

发布于 2025-01-17 11:13:52 字数 992 浏览 2 评论 0原文

我正在尝试编写一个bash脚本,该脚本将以参数的形式获取输入,并在远程主机上执行某些命令(作为参数),这些命令将通过TXT文件提供,

例如: .txt具有主机名,我们将执行一组命令。 我应该能够在hosts.txt文件中提供的远程主机上运行命令

lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'

当我运行脚本(command.sh)时, 这样:

command.sh -f hosts.txt -c "lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'"

它应该运行-c在Hosts XYZ上提供的命令,在执行SSH之后,

我能够使单行命令工作(whoami,hostName日期..)但是,当涉及命令的组合时,我未能实现这一目标,因为它将它们作为不同的参数集。

\#!/bin/bash

usage () {
    echo "Usage: $0 \<Hostfile\>"
    exit -1
}

id="rm08397"

while getopts ":c:f:" option; do

    case "$option" in
        f) file_arg=$OPTARG ;;
        c) command_arg="$OPTARG" ;;
    esac
done

if \[ "$file_arg" != "" \]; then
    HOSTFILE="$2"
fi

if \[ $command_arg != "" \]; then
    cmd="$command_arg"
else
    cmd=$4
fi

for host in `cat $HOSTFILE`
do
    echo -n "$host#"
    ssh $id@$host $cmd
done

I am trying to write a bash script which will take the input in form of arguments and execute certain commands (provided as arguments) on the remote hosts which will be provided via txt file

For eg: there is text file /var/tmp/hosts.txt which have hostnames which we will be executing a set of commands.
When I run the script (command.sh) I should be able to run commands on the remote hosts provided in the hosts.txt file

For instance: Hosts file - hosts.txt and Command to be executed is:

lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'

I should be able to execute in this way:

command.sh -f hosts.txt -c "lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'"

and it should run the command provided in the -c argument on hosts xyz after doing an ssh

I was able to get single line commands working (whoami, hostname date .. ) but when it comes to combination of commands, I failed to achieve that because it takes them as different set of arguments.

\#!/bin/bash

usage () {
    echo "Usage: $0 \<Hostfile\>"
    exit -1
}

id="rm08397"

while getopts ":c:f:" option; do

    case "$option" in
        f) file_arg=$OPTARG ;;
        c) command_arg="$OPTARG" ;;
    esac
done

if \[ "$file_arg" != "" \]; then
    HOSTFILE="$2"
fi

if \[ $command_arg != "" \]; then
    cmd="$command_arg"
else
    cmd=$4
fi

for host in `cat $HOSTFILE`
do
    echo -n "$host#"
    ssh $id@$host $cmd
done

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雪化雨蝶 2025-01-24 11:13:52

有很多方法可以尝试这样做,但是由于单词分裂和引用,这很难。

我建议这样的运行SSH:

ssh $id@$host /bin/bash -c "$cmd"

这是让我们远程打击来解析命令。

在下面的评论中,您说的是,它没有在-c之后捕获整个命令。问题不是脚本,而是您如何调用它。您将参数的双引号用于-c,但是在该参数中,您使用了更多的双引号。这些导致解析器尽早结束命令。如果您在脚本中打印出命令变量,您将看到其停止的位置。为了解决此问题,只需在命令字符串中的任何双引号之前放置后斜切,或者在那里使用单个引号。

command.sh -f hosts.txt -c "lscpu | grep \"Model name\" | cut -d: -f2 | awk '{$1=$1};1'"

There are many ways to try to do this, but it's tough because of word splitting and quoting.

I would recommend running ssh like this:

ssh $id@$host /bin/bash -c "$cmd"

This let's remote bash take care of parsing the command.

In the comment below you are saying that it is not capturing the whole command after -c. The problem is not with the script but with how you invoke it. You use double quotes for the argument to -c, but within that argument you use more double quotes. Those cause the parser to end the command early. If you print out the command variable in the script you will see where it stops. To fix this, just put backslashes before any double quotes in the command string, or use single quotes there instead.

command.sh -f hosts.txt -c "lscpu | grep \"Model name\" | cut -d: -f2 | awk '{$1=$1};1'"
携君以终年 2025-01-24 11:13:52

通过SSH将工作转移到遥控器很难。不要关心适当的双重引用。正确序列化数据NAD代码。

创建一个函数来运行远程命令。

func() {  ....; }

然后重新格式化程序以将函数正确序列到遥控器并运行它。

...
-c) command_arg=$OPTARG; ;;
...
while IFS= read -r host; do
    echo -n "$host#"
    # magic
    # run bash -c on the remote side
    # with `declare -f <the_function>` serialization of the function
    # followed by `; <the_function>` actually exeucting the function
    ssh "$id@$host" "$(printf "%q " bash -c "$(declare -f "$command_arg"); $command_arg")"
done <"$hostfile"

然后,您可以做:

func() { lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'; }
export -f func
./command.sh -f hosts -c func

请注意,您不必正确关心\“ \” double引用命令。请记住使用ShellCheck检查您的脚本。请勿使用背景。

Transfering work to the remote via ssh is uterrly hard. Do not care about proper double-quoting. Properly serialize data nad code.

Create a function to run the remote commands.

func() {  ....; }

Then reformat your program to properly serialize the function to the remote and run it.

...
-c) command_arg=$OPTARG; ;;
...
while IFS= read -r host; do
    echo -n "$host#"
    # magic
    # run bash -c on the remote side
    # with `declare -f <the_function>` serialization of the function
    # followed by `; <the_function>` actually exeucting the function
    ssh "$id@$host" "$(printf "%q " bash -c "$(declare -f "$command_arg"); $command_arg")"
done <"$hostfile"

Then you can do:

func() { lscpu  | grep "Model name" | cut -d: -f2 | awk '{$1=$1};1'; }
export -f func
./command.sh -f hosts -c func

Note that you do not have to care about properly \"\" double quoting your command. Remember to check your script with shellcheck. Do not use backticks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文