问题
This works from my local terminal:
ssh -i ~/.ec2/mykey.pem ubuntu@ec2-yada-yada.amazonaws.com ls
Of course it does. But when I try the same using node.js' child_process.spawn
command it complains that the key does not exist / can't be accessed.
// child process
var childProcess = require('child_process').spawn;
// spawn the slave using slaveId as the key
slaves[slaveId] = childProcess('ssh', [
'-i /mykey.pem',
'ubuntu@ec2-yada.amazonaws.com',
'ls'
])
Result:
stderr: Warning: Identity file /mykey.pem not accessible: No such file or directory.
stderr: Permission denied (publickey).
Things tried:
Variations on the path to key:
/actual/path/to/mykey.pem
mykey.pem
(with a copy of the file in the root of the node project)/mykey.pem
(with a copy of the file in the root of the node project)~/.ec2.mykey.pem
(where it should be)Running the command without the ssh part, ie.
childProcess(ls);
- works.chmod 644, 600, 400 etc. mykey.pem
My only theory at this point is there is an issue with passing a file reference in and I need to do something using the fs module. (?) And yes, I know there are libraries out there for ssh access with node but they use passwords which won't cut it and anyway, my requirements don't really justify a library.
Please tell me I'm being stupid and that this is possible.
UPDATE:
OK, so I can use the exec command like this:
var childProcess = require('child_process').exec;
slaves[slaveId] = childProcess('ssh -i mykey.pem ubuntu@ec2-yada.amazonaws.com ls', function (error, stdout, stderr) {...}
Still, I feel like I've been downgraded from creating a true slave using fork
with all it's nice messaging and handy properties (my original implementation which runs fine locally) to having a vacuum cleaner and being told to do all the work myself (now that I want to launch slaves on remote hosts).
回答1:
I seem to be jumping Brandon's comments a lot lately :-). He's right again. When you execute ssh -i ~/.ec2/mykey.pem ubuntu@ec2-yada-yada.amazonaws.com ls
, the ssh
executable, in this case, gets four arguments: -i
, the name of your key file, the address of the host and the command, eg. ls -ltr /tmp
. When it sees a -i
it expects the next argument to be the name of the key file, not to see the name as a trailing substring of the -i
.
Remember that when you spawn
a program, you invoke it directly without going through the shell, so you have to pass it exactly the arguments the shell would have passed it after the shell did any expansion, quoting, etc. When you use exec
, you're actually passing a command-line string to the shell, so the shell does all that stuff for you, including figuring out where one arguments ends and another begins.
来源:https://stackoverflow.com/questions/12333070/how-to-pass-a-key-file-when-spawning-an-ssh-command-from-node-js