我尝试使用节点进程启动交互式docker会话,然后自动执行一些命令:
var spawn = require('pty.js').spawn;
var proc = spawn('docker', [ 'run', '-i', '-t', 'mycontainer' ], {
name: 'test',
rows: 30,
cols: 200,
cwd: process.env.HOME,
env: process.env
});
proc.on('data', function (data) {
console.log(data);
});
proc.write('cd /tmp');
proc.write('nvm install 0.10\r');
proc.write('npm install');

这似乎有效,唯一的问题是它似乎只是在所有命令中编写并解雇它们。我似乎无法控制捕获单个命令的输出或错误。
我很好奇是否有更好的方法来解决这个问题?
答案 0 :(得分:1)
您可以通过管道将流传输到此过程,但是不建议这样做。
#include <stdio.h>
#include <cs50.h>
int main(void)
{
int i , j , k , Height ;
Height = get_int("Enter desired pyramid height between 1 and 8: ");
while (!((Height<=8 && (Height>=1)))
{
Height = get_int("Enter desired pyramid height between 1 and 8: ");
}
if (Height>0 && Height<9)
{
for (i=0;i<Height;i++)
{
for(j=0;j<(Height-1-i);j++)
{
printf(" ");
}
for(k=i+1;k>0;k--)
{
printf("#");
}
printf(" ");
for(k=i+1;k>0;k--)
{
printf("#");
}
printf("\n");
}
}
}
不要像流一样使用pty的maintainer have suggested。只需更改类似这样的管道即可。
const { pipeline } = require('stream');
const { spawn } = require('node-pty')
const proc = spawn('docker', ['run', '--rm', '-ti', 'alpine', '/bin/sh'], {
name: 'xterm-color',
cwd: process.env.HOME,
env: process.env,
encoding: null,
});
pipeline(process.stdin, proc, (err) => err && console.warn(err.message))
pipeline(proc, process.stdout, (err) => err && console.warn(err.message))
要点是我们应该将字符串传递给write函数。我们还应该期望将字符串作为其输出。因此,我们不应在对象中设置任何编码,以便默认情况下它会输出utf8字符串。
关于您最初的问题。 (async (stream) => {
for await (const chunk of stream) {
proc.write(chunk.toString())
}
})(process.stdin).catch(console.warn)
是正确的方法。注意尾随proc.write('ls\r')
以虚拟方式按Enter。就像在普通终端中一样,当您执行命令时,不能同时触发第二个命令。这些命令只会排队并一个接一个地运行。
输入:
\r
输出:
const { spawn } = require('node-pty')
const proc = spawn('docker', ['run', '--rm', '-ti', '--network=host', 'node', '/bin/sh'], {
name: 'xterm-color',
cwd: process.env.HOME,
env: process.env,
});
proc.write('npm init -y\r')
proc.write('npm i eslint\r')
proc.write('ls node_modules /\r')
const disposable = proc.onData((text) => process.stdout.write(text))
const exitDisposable = proc.onExit(() => {
disposable.dispose()
exitDisposable.dispose()
})
您看到它在npm安装完成之前写了ls,但是后来运行了。
还请注意,我为码头工人参数使用了npm i eslint
ls node_modules /
# Wrote to /package.json:
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"lib": "lib"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN @1.0.0 No description
npm WARN @1.0.0 No repository field.
+ eslint@7.1.0
added 136 packages from 82 contributors and audited 136 packages in 9.461s
9 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
# /:
bin etc lib64 node_modules package.json run sys var
boot home media opt proc sbin tmp
dev lib mnt package-lock.json root srv usr
node_modules:
@babel is-extglob
@types is-fullwidth-code-point
...
...
#
而不是-ti
。
答案 1 :(得分:0)
查看pty.js
模块的来源,很明显您的proc.write
确实是标准节点net.Socket.write
- https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback
简而言之,是的,您只是将命令垃圾邮件发送到套接字。在执行下一个命令之前,您需要等待每个命令完成。因此,您需要使用.write
的回调参数来确定命令何时完成,然后从那里继续。这样的事情可能有用:
// this is a quick and dirty hack
let cmdcount = 0;
function submitcmd() {
switch (cmdcount) {
case 0:
proc.write('nvm install 0.10\r', 'utf8', submitcmd);
break;
case 1:
proc.write('npm install', 'utf8', submitcmd);
break;
}
cmdcount += 1;
}
proc.write('cd /tmp', 'utf8', submitcmd);