如何通过Node.js从本地机器连接服务端终端并发送命令
Hey there! Let's figure out how to connect to a remote server's terminal from your local Node.js code. The child_process module works great for running commands on your own machine, but for remote servers, we need to use SSH—since that's the standard way to securely access remote terminals. Here's how to do it properly:
1. Pick an SSH Library for Node.js
First, you'll need a Node.js library that wraps SSH functionality. Two popular options are:
ssh2: A flexible, low-level library that gives you full control over the SSH connectionsimple-ssh: A simpler wrapper aroundssh2for basic use cases
For most scenarios, ssh2 is the way to go because it handles both one-off commands and interactive sessions. Install it via npm:
npm install ssh2
2. Run One-Off Commands on the Remote Server
If you just need to send a single command (like ls, uptime, or a script) and get the output, use the exec method. Here's a complete example:
const { Client } = require('ssh2'); // Initialize the SSH client const sshClient = new Client(); // Handle connection errors sshClient.on('error', (err) => { console.error(`Connection failed: ${err.message}`); }); // When connection is ready, execute your command sshClient.on('ready', () => { console.log('Successfully connected to the remote server!'); // Run a command on the remote terminal sshClient.exec('ls -la /home', (err, stream) => { if (err) throw err; // Capture standard output from the command stream.on('data', (output) => { console.log(`Remote server output:\n${output}`); }); // Capture error output stream.stderr.on('data', (error) => { console.error(`Remote server error:\n${error}`); }); // When the command finishes, close the connection stream.on('close', (exitCode) => { console.log(`Command exited with code ${exitCode}`); sshClient.end(); // Clean up the connection }); }); }); // Connect to the remote server sshClient.connect({ host: 'your-server-ip-or-domain', // e.g., '192.168.1.100' or 'example.com' port: 22, // Default SSH port (change if your server uses a different one) username: 'your-ssh-username', // e.g., 'root' or a dedicated user // Use either password or private key for authentication password: process.env.SSH_PASSWORD, // Never hardcode passwords! Use env vars // privateKey: require('fs').readFileSync('/path/to/your/private-key.pem') // More secure option });
Important Notes for This Example:
- Never hardcode credentials: Use environment variables (like
process.env.SSH_PASSWORD) or a secure config file instead of writing passwords directly in your code. - Private key authentication is safer: If your server allows it, use a private key instead of a password. Just replace the
passwordfield withprivateKeypointing to your local key file.
3. Create an Interactive Terminal Session
If you need a full interactive session (like typing multiple commands, responding to prompts, or using tools like vim), use the shell method instead of exec. This mimics opening a real terminal window on the server:
const { Client } = require('ssh2'); const sshClient = new Client(); sshClient.on('ready', () => { console.log('Connected—starting interactive shell session'); sshClient.shell((err, stream) => { if (err) throw err; // Send a command to the shell (don't forget the newline character!) stream.write('echo "Hello from local Node.js!"\n'); // Capture all output from the shell stream.on('data', (output) => { console.log(`Shell output:\n${output}`); }); // Handle errors from the shell stream.stderr.on('data', (error) => { console.error(`Shell error:\n${error}`); }); // When the shell session closes stream.on('close', () => { console.log('Interactive session ended'); sshClient.end(); }); // Example: Send another command after 2 seconds setTimeout(() => { stream.write('uptime\n'); }, 2000); }); }).connect({ host: 'your-server-ip', port: 22, username: 'your-username', privateKey: require('fs').readFileSync('/path/to/your/private-key.pem') });
This will let you send commands sequentially and interact with any prompts the server sends back (like password prompts for sudo commands—though you'll need to handle input for those manually).
4. Additional Tips
- Handle disconnections: Add an
endevent listener to know when the connection closes unexpectedly:sshClient.on('end', () => console.log('Connection closed')); - Batch commands: For multiple one-off commands, you can chain
execcalls inside thereadyevent, or use promises to make the code cleaner. - Error handling: Always include error listeners to avoid uncaught exceptions in your Node.js app.
内容的提问来源于stack exchange,提问作者Andrey Radkevich

