AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1098053
Accepted
Janith
Janith
Asked: 2018-12-03 19:37:16 +0800 CST2018-12-03 19:37:16 +0800 CST 2018-12-03 19:37:16 +0800 CST

SSH 如何在 if 条件下工作?

  • 772

我有一个if语句来计算文件并删除除了最新的三个文件之外的所有文件。但我想远程运行这个命令。如何ssh与if条件结合?

我试过这个但没有成功。

#!/bin/bash

ssh -t  [email protected] "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"

我得到的错误:

ls: 无法访问 *.tgz: 没有这样的文件或目录

command-line ssh bash
  • 4 4 个回答
  • 18071 Views

4 个回答

  • Voted
  1. Simon Sudler
    2018-12-04T00:11:45+08:002018-12-04T00:11:45+08:00

    是的,您可以通过以下方式执行复杂的脚本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 [email protected] "$ssh_cmd"
    

    此示例使用 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"
    

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

    • 12
  2. Best Answer
    pt314
    2018-12-04T05:19:41+08:002018-12-04T05:19:41+08:00

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

    您的命令行大多是正确的;您只需要稍微更改报价即可。

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

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

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

    #!/bin/bash
    
    ssh -t  [email protected] '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'
    
    • 6
  3. PerlDuck
    2018-12-04T05:44:29+08:002018-12-04T05:44:29+08:00

    我认为这整个复杂的引用内容足以证明不使用它,而是使用脚本。如果您想避免多个 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
    

    然后:

    cat myscript.sh | \
        ssh -t [email protected] \
        "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh"
    

    或者(避免对 cat 的无用使用):

    ssh -t [email protected] \
        "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh" \
        < myscript.sh
    

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

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

    • 4
  4. pa4080
    2018-12-04T01:51:06+08:002018-12-04T01:51:06+08:00

    我更愿意将脚本放在远程实例上并通过 ssh 执行它,但这是我的建议,如何以您想要的方式完成:

    #!/bin/bash
    
    HOST='[email protected]'
    REMOTE_PATH='/var/www/test.com/backup'
    
    COMMAND1="ssh \"$HOST\" 'ls \"$REMOTE_PATH\" | wc -l'"
    COMMAND2="ssh \"$HOST\" 'ls -t \"$REMOTE_PATH\"/*.tgz'"
    COMMAND3="xargs ssh \"$HOST\" rm -rf"
    
    if [[ $(eval "$COMMAND1") -le 3 ]]
    then
        echo "Less"
    else
        eval "$COMMAND2" | awk 'NR > 3' | eval "$COMMAND3" && echo "Deleted"
    fi
    

    笔记:

    • 条件表达式-lt被替换-le。
    • eval- 通过连接参数构造命令。
    • 我不确定我们是否真的需要\"在$COMMAND{1..3}表达式中添加这些额外的引号,但我决定添加它们。
    • 3

相关问题

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

  • 如何与无头服务器进行图形交互?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve