zoukankan      html  css  js  c++  java
  • 【转】ssh 远程执行命令

    原文:https://blog.csdn.net/liuxiao723846/article/details/82667482

    SSH 是 Linux 下进行远程连接的基本工具,不光可以登录,也可以远程操作。接下来我们详细讲解一些常用的情况。

    1、执行简单的命令:

    1)查看某台主机上的磁盘使用情况:

    $ ssh root@1.113.195.138 "df -h"
    ***************************************************************************
    NOTICE TO Users
    
    This computer system is the private property of ...
    
    ***************************************************************************
    
    Filesystem Size Used Avail Use% Mounted on
    /dev/vda2 36G 3.2G 31G 10% /
    tmpfs 25G 0 25G 0% /dev/shm
    /dev/vdb 296G 2.0G 279G 1% /data

    可以看到会把ssh远程连接的信息,以及远程执行名的返回的信息都输出到了控制台上。

    2)保存远程执行命令结果:

    有时我们需要保存远程执行命令的结果,然后进行判断。有两种方法:

    赋值的方式:result=`ssh x@B ~/command.sh`
    追加到文件:ssh root@$ip "cmd" >> ./log

    详情见:https://blog.csdn.net/liuxiao723846/article/details/55045988

    3)一次执行多个命令:

    在shell中单行语句一般要用到分号来区分代码块,多行的话用换行符来区分代码块,则无需用到分号。

    $ if [ "$PS1" ]; then echo test is ok; fi
    test is ok
    
    如果换做多行
    $if [ "PS1" ]
    > then echo "test is ok"
    > fi
    test is ok

    所以,我们可以在ssh中用分好拼接多个命令

    1 ssh root@$IP "if [ -e /lib64/libpcre.so.1 ];then echo 'file exits...';else cd /lib64 && ln -s libpcre.so.0.0.1 libpcre.so.1;fi"

    2、执行需要交互的命令:

    有时候我们需要远程执行一些有交互操作的命令,如下:

    $ ssh nick@xxx.xxx.xxx.xxx "sudo ls /root"
    $ ssh nick@xxx.xxx.xxx.xxx "top"

    这两条命令虽然提示的失败原因不同,但它们有一个共同点:都需要与用户交互(需要 TTY)。所以它们失败的原因也是相同的:
    默认情况下,当你执行不带命令的 ssh 连接时,会为你分配一个 TTY。因为此时你应该是想要运行一个 shell 会话。
    但是当你通过 ssh 在远程主机上执行命令时,并不会为这个远程会话分配 TTY。此时 ssh 会立即退出远程主机,所以需要交互的命令也随之结束。
    好在我们可以通过 -t 参数显式的告诉 ssh,我们需要一个 TTY 远程 shell 进行交互!
    添加 -t 参数后,ssh 会保持登录状态,直到你退出需要交互的命令。

    3、执行本地脚本:

    通常我们遇到的不会是上面那种简单的问题,大多数时候我们需要把若干个命令放到一个脚本里,然后分发到远程去执行。大致有两种思路:

    使用scp将本地脚本文件拷贝到远端,然后再通过ssh执行远端的脚本;(弊端是脚本修改后,每次都需要scp)
    直接在本地执行脚本到远程;
    一个scp的例子

    1 for IP in ${IP_ARR[@]}
    2 do
    3 ssh root@$IP "rm -rf $MONITOR_TARGET_FILE" 
    4 ssh root@$IP "mkdir -p /data/apps/scripts"
    5 scp $MONITOR_SOURCE_FILE root@$IP:$MONITOR_TARGET_FILE
    6 ssh root@$IP 'echo "*/1 * * * * /usr/bin/python /data/apps/scripts/checkStatus.py' $BUSINESS_TYPE '>/dev/null 2>&1" >> /var/spool/cron/root'
    7 
    8 done

    重点我们在如何在本地执行脚本到远程。

    1)执行一个简单的脚本到远程:

    1 $ cat test.sh 
    2 ls
    3 pwd
    4 
    5 $ ssh root@10.153.195.138 < test.sh 
    6 anaconda-ks.cfg
    7 /root

    通过重定向 stdin,本地的脚本 test.sh 在远程服务器上被执行。

    2)为脚本传递参数:

     1 $ cat test.sh 
     2 echo $1
     3 echo $2
     4 
     5 在本地执行结构如下:
     6 $ sh test.sh a b
     7 a
     8 b
     9 
    10 通过重定向远程执行,会报错
    11 $ ssh root@10.153.195.138 < test.sh a b
    12 bash: a: command not found

    看来上面的方法都无法为脚本传递参数。
    要想在这种情况下(远程执行本地的脚本)执行带有参数的脚本,需要为 bash 指定 -s 参数:

    1 $ ssh root@10.153.195.138 'bash -s' < test.sh a b
    2 a
    3 b

    除此之外,我们还可以通过替换的方式传参,然后远程执行,例如:

    1 cat ./rollback_remote.sh | sed -e "s/#module#/${MODULE_NAME}/g" -e "s/#runarg#/${RUN_ARG}/g" | ssh $IP

    4、执行远程服务器上的脚本:

    除了执行本地的脚本,还有一种情况是脚本文件存放在远程服务器上,而我们需要远程的执行它!此时在远程服务器上用户 nick 的家目录中有一个脚本 test.sh。文件的内容如下:

    1 ls
    2 pwd
    3 执行下面的命令即可(注:一定是绝对路径):
    4 $ ssh nick@xxx.xxx.xxx.xxx "/home/nick/test.sh"

    下面我们也尝试为脚本传递参数。在远程主机上的 test.sh 文件的末尾添加两行:

    1 echo $0
    2 echo $1
    3 然后尝试执行下面的命令:
    4 
    5 $ ssh nick@xxx.xxx.xxx.xxx /home/nick/test.sh helloworld

    可以正确得到结果。

    5、执行多行命令:

    有时候我们可能需要随手写几行简单的逻辑,这也没有问题,ssh 能轻松搞定!

    1 $ ssh root@10.153.195.138 "
    2 > ls
    3 > pwd
    4 > "
    5 anaconda-ks.cfg
    6 /root

    你可以用单引号或双引号开头,然后写上几行命令,最后再用相同的引号来结束。

    当我们在命令中引用了变量时会怎么样呢?

    1 $ name=test
    2 $ ssh root@10.153.195.138 "
    3 > echo $name
    4 > "
    5 test
    6 
    7 $ ssh root@10.153.195.138 '
    8 echo $name
    9 '

    最后一行,并没有输出我们期望的 test。这里多少有些诡异,因为如果变量没有被解释的话,输出的应该是 $name 才对。但是这里却什么都没有输出。对于引用变量的写法,可以通过bash 指定了 -c 参数方式保证变量被正确解释:

    1 $ ssh root@10.153.195.138 bash -c "'
    2 echo $name
    3 '"
    4 test
  • 相关阅读:
    BZOJ3160: 万径人踪灭(FFT,回文自动机)
    BZOJ4044: [Cerc2014] Virus synthesis(回文树+DP)
    codeforces 666E. Forensic Examination(广义后缀自动机,Parent树,线段树合并)
    BZOJ3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
    BZOJ5137: [Usaco2017 Dec]Standing Out from the Herd(广义后缀自动机,Parent树)
    BZOJ4516: [Sdoi2016]生成魔咒(后缀自动机)
    codeforces 235C. Cyclical Quest(后缀自动机)
    codeforces 204E. Little Elephant and Strings(广义后缀自动机,Parent树)
    BZOJ2119: 股市的预测(后缀数组)
    BZOJ2555: SubString(后缀自动机,LCT维护Parent树)
  • 原文地址:https://www.cnblogs.com/HYanqing/p/11687378.html
Copyright © 2011-2022 走看看