简体   繁体   English

SSH与nodejs

[英]SSH with nodejs

Attempting to create files and such on new vps that was created using api. 尝试在使用api创建的新vps上创建文件等。 This function does not run the second ssh command for some reason. 由于某种原因,此函数不运行第二个ssh命令。 Before this function is run there's another that is also run that sends a few commands to install packages before it installs the files. 在运行此函数之前,还运行另一个函数,它在安装文件之前发送一些命令来安装软件包。 I have the function running after a timer has run out so that it can use some of the packages to run the commands like screen. 我在定时器用完后运行该函数,以便它可以使用一些软件包来运行像屏幕这样的命令。 It runs the first ssh but not the second one and i have tried with a timer up to 180 seconds. 它运行第一个ssh而不是第二个ssh,我尝试使用计时器长达180秒。

function CreateServer( SIP, GUSER, SPORT ) {
var CDir = "";
var RPassword = generator.generate({
    length: 10,
    numbers: true
});
var ssh = new SSH({
    host: SIP,
    user: 'root',
    key: fs.readFileSync('serverkey.ppk')
    //pass: 'password'
});

ssh.exec('if test -d /home/' + GUSER + '; then echo "exist"; fi', {
    out: function(stdout) {
        CDir = stdout;
        //console.log(stdout);
    }
}).start();
setTimeout(function(){
    if(CDir == DMkdir) {
        console.log("User on machine not adding......");
        ssh.exec('chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
            out: function(stdout) {
                //console.log(stdout);
            }
        }).start();             
    } else {
        console.log("User not on machine adding......");
        ssh.exec('cd /home/; sudo adduser ' + GUSER + ' --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password; echo "' + GUSER + ':' + RPassword + '" | sudo chpasswd; cd /home/' + GUSER + '/; mkdir steamcmd; cd /home/' + GUSER + '/steamcmd; wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz; tar -xvzf steamcmd_linux.tar.gz; chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
            out: function(stdout) {
                console.log(stdout);
            }
        }).start();
    }
}, 5 * 1000);
return true;

} }

I'm assuming everything is correct besides your problem with handling two asynchronous events. 除了你处理两个异步事件的问题之外,我假设一切都是正确的。 Given that I can't see where DMkdir is coming from and just of context of your other code I am assuming that just like CDir its value is being set asynchronously. 鉴于我无法看到DMkdir的来源以及其他代码的上下文,我假设就像CDir一样,它的值是异步设置的。

Assuming your using a recent version of node that uses native promises like Node version 6 and up then the following code will work for you. 假设您使用的是最近版本的节点,该节点使用本地承诺(如节点版本6及更高版本),则以下代码将适用于您。 If your not using a more recent version of node you can use a promise library like bluebird or Q which will involve different syntax but it will be solved a similar way. 如果你没有使用更新版本的节点,你可以使用像bluebirdQ这样的诺言库,这将涉及不同的语法,但它将以类似的方式解决。

function sshPromise (string) {
    new Promise((resolve, reject) => {
      ssh.exec(string, {
          // on correct output the promise needs to be 
          // resolved by calling the resolve function with the data
          out: resolve
          // not sure what the error property is but it needs 
          // to reject the promise with the error data
          onError: reject
      }).start();
    });
}

var CDirPromise = sshPromise('if test -d /home/' + GUSER + '; then echo "exist"; fi');

var DMkdirPromise = sshPromise('whatever command you did for this one obviously not this string');

Promise.all([CDirPromise, DMkdirPromise]).then(function ([CDir, DMKdir]) {
    // this then method will fire when all the promises resolve.
    if(CDir == DMkdir) {
        console.log("User on machine not adding......");
        ssh.exec('chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
            out: function(stdout) {
                //console.log(stdout);
            }
        }).start();             
    } else {
        console.log("User not on machine adding......");
        ssh.exec('cd /home/; sudo adduser ' + GUSER + ' --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password; echo "' + GUSER + ':' + RPassword + '" | sudo chpasswd; cd /home/' + GUSER + '/; mkdir steamcmd; cd /home/' + GUSER + '/steamcmd; wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz; tar -xvzf steamcmd_linux.tar.gz; chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
            out: function(stdout) {
                console.log(stdout);
            }
        }).start();
    }
}).catch(function (err) {
    // handle the error one of the promises rejected.
});

You should do handling of errors as well (when saying ssh.exec there should be a way to handle the error output I just guessed it was onError but you should change it to what it actually is. I don't know what ssh library you are using so I just guessed it was onError .) as it seems currently that your code is not checking for errors being thrown. 你也应该处理错误(当说ssh.exec应该有一种方法来处理错误输出我只是猜测它是onError但你应该把它改成它实际上是什么。我不知道什么是ssh库你正在使用所以我猜它是onError 。)因为目前看来你的代码没有检查抛出的错误。

I'll write just a bit about promises. 我会写一些关于承诺的文章。 They are very good for asynchronous events that happen once. 它们非常适合发生一次的异步事件。 They are also good at handling errors with these asynchronous events. 他们也擅长处理这些异步事件的错误。 A promise has three states: 'pending' which is an unfinished state, 'resolved' which is a successful finished state, or rejected which is an unsuccessful finished state likely caused by an error. 承诺有三种状态:'待定',即未完成状态,'已解决',即成功完成状态,或被拒绝,这是可能由错误引起的不成功完成状态。 You can handle resolved values in a promise with a .then method and handle rejected values with the .catch method. 您可以使用.catch方法处理promise中的已解析值.then并使用.catch方法处理被拒绝的值。

I suggest reading the below links about Promises to truly get a grasp on them. 我建议阅读以下关于Promises的链接,以真正掌握它们。

Good luck. 祝好运。 :) :)

EDIT: 编辑:

Well according to the comments the problem is quite a bit simpler. 根据评论,这个问题相当简单。 All you really need to do is the following which is to just put your function to run after CDir is available on the out property of ssh.exec. 所有你真正需要做的就是在ssh.exec的out属性上提供CDir后才能运行你的函数。

ssh.exec('if test -d /home/' + GUSER + '; then echo "exist"; fi', {
    out: function (CDir) {
        if(CDir == DMkdir) {
            console.log("User on machine not adding......");
            ssh.exec('chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
                out: function(stdout) {
                    //console.log(stdout);
                }
            }).start();             
        } else {
            console.log("User not on machine adding......");
            ssh.exec('cd /home/; sudo adduser ' + GUSER + ' --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password; echo "' + GUSER + ':' + RPassword + '" | sudo chpasswd; cd /home/' + GUSER + '/; mkdir steamcmd; cd /home/' + GUSER + '/steamcmd; wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz; tar -xvzf steamcmd_linux.tar.gz; chown -R ' + GUSER + ':' + GUSER + ' /home/' + GUSER + '; su - ' + GUSER + ' -c "cd /home/' + GUSER + '/steamcmd ; screen -mdSL ' + SIP + ':' + SPORT + ' ./steamcmd.sh +login anonymous +force_install_dir /home/' + GUSER + '/' + SIP + '.' + SPORT + ' +app_update 4020 validate +quit"', {
                out: function(stdout) {
                    console.log(stdout);
                }
            }).start();
        }
    }
}).start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM