This works from my local terminal:
ssh -i ~/.ec2/mykey.pem [email protected] 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',
'[email protected]',
'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 [email protected] 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).
The spawn function launches a command in a new process and we can use it to pass that command any arguments. For example, here's code to spawn a new process that will execute the pwd command. const { spawn } = require('child_process'); const child = spawn('pwd');
child_process.exec() : spawns a shell and runs a command within that shell, passing the stdout and stderr to a callback function when complete.
The exec() function in Node. js creates a new shell process and executes a command in that shell. The output of the command is kept in a buffer in memory, which you can accept via a callback function passed into exec() .
I seem to be jumping Brandon's comments a lot lately :-). He's right again. When you execute ssh -i ~/.ec2/mykey.pem [email protected] 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With