【问题标题】:How execute multiple commands on SSH2 using NodeJS如何使用 NodeJS 在 SSH2 上执行多个命令
【发布时间】:2014-01-21 07:52:25
【问题描述】:

我正在尝试从 GitHub 部署,我想按数组的顺序执行多个命令。我现在使用的代码如下。

async.series([
...
// Deploy from GitHub
function (callback) {
    // Console shizzle:
    console.log('');
    console.log('Deploying...'.red.bold);
    console.log();
    console.log();

    var deployFunctions = [
        {
            command: 'cd ' + envOptions.folder + ' && pwd',
            log: false
        },
        {
            command: 'pwd'
        },
        {
            command: 'su ' + envOptions.user,
            log: false
        },
        {
            command: 'git pull'
        },
        {
            command: 'chmod 0777 * -R',
            log: false
        }
    ];
    async.eachSeries(deployFunctions, function (item, callback) {
        deployment.ssh2.exec(item.command, function (err, stream) {
            deployment.logExec(item);
            stream.on('data', function (data, extended) {
                console.log(data.toString().trim());
                console.log();
            });
            function done() {
                callback(err);
            }

            stream.on('exit', done);
            stream.on('end', done);
        });
    }, function () {
        callback();
    });
},
...);

但是,当我 cd'ed 到正确的目录后,它忘记了它的位置并重新开始。

$ cd /some/folder && pwd
/some/folder

$ pwd
/root

【问题讨论】:

  • 但这并没有描述如何一个接一个地执行更多的命令,是吗?
  • 命令按顺序运行,并且可能每个都在不同的 shell 实例中,这意味着环境中的任何更改(如当前工作目录)都不是“粘性”。也许使用.shell 而不是.exec,尽管您可能必须重写执行命令的方式(或在每个命令前加上cd ... &&)。
  • 您建议如何使用.shell?我似乎找不到太多使用 node-ssh2 模块的例子,所以很难掌握它应该如何(正确地)使用。
  • 这里有一些想法:gist(恐怕不是特别漂亮)。您可能希望将 async 循环移动到 .shell 处理程序内部。
  • 一种解决方案是使用'cd ' + envOptions.folder + ' && pwd' 扩展您所拥有的内容,以构建一个包含您要执行的所有命令的字符串。回想一下,您可以使用 ;&&(如您所知)和 || 分隔 cmd。祝你好运。

标签: javascript node.js shell ssh node-modules


【解决方案1】:

一个实际的例子:

  const client = new Client();
  const cmds = [
    'ls -lah \n',
    'cd /mnt \n',
    'pwd \n',
    'ls -lah \n',
    'exit \n',
  ];
  client.on('ready', () => {
      console.log('Client :: ready');
      client.shell((err, stream) => {
        stream.on('close', (code) => {
          console.log('stream :: close\n', { code });
        }).on('data', (myData) => {
          console.log('stream :: data\n', myData.toString());
        }).on('exit', (code) => {
          console.log('stream :: exit\n', { code });
          client.end();
        }).on('error', (e) => {
          console.log('stream :: error\n', { e });
          rej(e);
        });
        for (let i = 0; i < cmds.length; i += 1) {
          const cmd = cmds[i];
          stream.write(`${cmd}`);
        }
      });
    }).connect({
    host: '127.0.0.1',
    port: 22,
    username: 'root',
    password: 'root',
  });

文档中的所有示例都使用stream.end(),这导致创建新会话而不是使用当前会话。

【讨论】:

    【解决方案2】:

    我知道这是一个非常古老的问题,但我在尝试通过我的节点服务器管理 ACE 时遇到了这个问题。答案对我不起作用,但后来几次搜索让我找到了一个非常适合我的包装器。只是想在这里分享,因为这是我 Google 搜索中的顶部链接。它被称为 ssh2shell,可以在这里找到:https://www.npmjs.com/package/ssh2shell

    使用起来非常简单,只需传递一组命令,它们就会一个接一个地运行,等待每个命令完成,然后再继续执行下一个命令。

    【讨论】:

      【解决方案3】:

      您不要在程序上使用“shell”,因为“Shell”命令会调用系统上的新终端并执行您的操作。您需要使用 "exec" 命令 而不发出 "exit" 。默认的“exec”命令在你给出的命令执行后发出“exit”命令。

      【讨论】:

      • 你能解释一下我们如何使用exec()而不发出exit事件并关闭连接吗?
      【解决方案4】:

      @robertklep 关于为什么你的cd 不存在是正确的。每个命令调用一个不同的 shell 实例,该实例以其初始状态开始。您可以在每个命令前加上 cd /home/jansenstok/domains/alcoholtesterwinkel.com/public_html/ &amp;&amp; 作为快速修复,但实际上您正在为自己准备痛苦。您需要的是一个具有多行功能的 shell 脚本,而不是单个断开连接的命令列表。

      看看使用ssh2的sftp函数将一个完整的shell脚本传输到远程机器上作为第1步,通过exec/bin/bash /tmp/your_deploy_script.sh)作为第2步执行,然后删除脚本作为第3步。

      【讨论】:

      • @Peter,这是一个不错的方法。顺便说一句,我们如何在原始终端中读取多个命令的输出。可以在每个命令之间放置 echo 语句作为分隔符,但我正在寻找一种更好的方法..
      • 默认情况下,如果您运行 bash 脚本,所有命令的输出都会被读取(stdout 和 stderr)。你不需要做任何特别的事情来获得它。
      猜你喜欢
      • 1970-01-01
      • 2014-09-17
      • 2020-09-14
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 2021-04-26
      相关资源
      最近更新 更多