SSH 如何在 if 条件下工作?

Jan*_*ith 9 ssh command-line bash

我有一个if语句来计算文件并删除除最新的三个文件之外的所有文件。但我想远程运行这个命令。我怎样才能sshif条件结合?

我试过这个,但没有成功。

#!/bin/bash

ssh -t  test@192.168.94.139 "cd /var/www/test.com/backup ;

if [ $(ls  | wc -l) -lt 3  ]
then
    echo "Less"
else [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]
    echo "deleted"
fi"
Run Code Online (Sandbox Code Playgroud)

我得到的错误:

ls: 无法访问 *.tgz: 没有那个文件或目录

Sim*_*ler 11

是的,您可以通过以下方式执行复杂的脚本 ssh

#!/bin/bash -e

ssh_cmd="$(cat <<-EOF
    cd /var/www/test.com/backup;

    if [ \$(ls  | wc -l) -lt 3  ]; then
        echo "less"
    elif [ \$(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
        echo "deleted"
    else
        echo "something else"
    fi
EOF
)"

ssh -t test@192.168.94.139 "$ssh_cmd"
Run Code Online (Sandbox Code Playgroud)

此示例使用 bash here 文档来生成命令字符串。在任何情况下,通过 ssh 传递脚本都容易出错,因为引用和转义变量很困难(注意命令前的反斜杠)。如果脚本太复杂,最好通过复制它scp,然后在目标主机上执行它。

我没有尝试修复您的脚本,但这里有一个示例,说明如何在远程主机上进行计数和删除:

#!/bin/bash -e

tmp_dir="$(mktemp -d)"

ssh_cmd="$(cat <<-EOF
    cd "$tmp_dir"

    cnt_tgz=(\$(find . -type f -name "*.tgz"))
    if [[ \${#cnt_tgz[@]} -lt 3 ]]; then
        echo "less"
    else
        rm "\${cnt_tgz[@]}"
        echo "deleted"
    fi
EOF
)"

touch "$tmp_dir/1.tgz"
ssh -t localhost "$ssh_cmd"
touch "$tmp_dir/2.tgz" "$tmp_dir/3.tgz"
ssh -t localhost "$ssh_cmd"
Run Code Online (Sandbox Code Playgroud)

ls -t *.tgz将不起作用,因为globbing只发生在本地系统上。同样ls用于计算文件也不是一个好主意,因为它还会返回像.,..和目录这样的条目。


pt3*_*314 6

注意:这里的问题实际上有两层。一个是“我想在可通过 SSH 访问的远程服务器上执行一项重要任务”。另一个是“我试图将一个复杂的字符串传递给一个命令,但该参数最终与我想要的不同。” 我在回答低级问题时没有讨论所使用的方法是否“正确”(方便、不易出错、安全等)来解决高级问题。正如其他答案和评论所示,它很可能不是。

你的命令行大部分是正确的;你只需要稍微改变一下引用。

主要问题是双引号字符串由您的本地 shell 扩展,因此这些$(...)部分将在您的本地系统上进行评估。要将它们传递给远程系统,您必须将脚本括在单引号中。

您还有一些嵌入式引号。在您的原始脚本中,有两个echos的参数;如果您将外部引号更改为单引号,它将是 awk 脚本。这些有效地导致引号被省略,这不会打扰echos,但它会弄乱 awk 脚本,因为大于号将成为输出重定向。因此,在将外部引号更改为单引号之后,请将它们更改为双引号。

这是您的脚本,引用已修复。脚本可能有其他问题,我只是修复了语法。

#!/bin/bash

ssh -t  test@192.168.94.139 'cd /var/www/test.com/backup ;

if [ $(ls  | wc -l) -lt 3  ]
then
  echo "Less"
else [ $(ls -t *.tgz|awk "NR >3"|xargs rm -f) ]
  echo "deleted"
fi'
Run Code Online (Sandbox Code Playgroud)


Per*_*uck 5

我认为这整个复杂的引用内容足以证明不使用它而是使用脚本。如果您想避免多个 ssh连接,请将脚本通过管道传输到另一台主机,并让它在一个命令中运行:

本地文件,例如myscript.sh

cd /var/www/test.com/backup;

if [ $(ls  | wc -l) -lt 3  ]; then
    echo "less"
elif [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
    echo "deleted"
else
    echo "something else"
fi
Run Code Online (Sandbox Code Playgroud)

然后:

cat myscript.sh | \
    ssh -t test@192.168.94.139 \
    "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh"
Run Code Online (Sandbox Code Playgroud)

或者(避免无用地使用 cat):

ssh -t test@192.168.94.139 \
    "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh" \
    < myscript.sh
Run Code Online (Sandbox Code Playgroud)

这会将本地脚本通过管道传输myscript.sh到远程端,并在远程端将其重定向到(临时)文件/tmp/ms.sh、执行并最终删除。

注意:我没有检查原始脚本是否有错误,只是想展示这个想法。不需要容易出错的引用,并且脚本中的所有命令都在远程端执行。

  • 但请记住,只有当脚本本身不尝试从标准输入读取时,重定向才有效。 (2认同)