我使用fork()和execvp()来生成一个进程,该进程必须相信它已连接到交互式终端才能正常运行.
一旦产生,我想捕获进程的所有输出,并且能够将输入发送到进程.
我怀疑psuedo-ttys可能会有所帮助.有没有人有关于如何做到这一点的片段?
所以我有这个测试代码通过USB串口发送"HELLO":
int fd;
struct termios tty;
if((fd = open("/dev/ttyUSB0", O_WRONLY|O_NONBLOCK|O_NOCTTY)) == -1){
err(1, "Cannot open write on /dev/ttyUSB0");
}
tcgetattr(fd, &tty);
tty.c_iflag = 0;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, B19200);
cfsetispeed(&tty, B19200);
tty.c_cflag |= CREAD|CRTSCTS|HUPCL|CS8;
tcsetattr(fd, TCSANOW, &tty);
printf("Write: %i\n", write(fd, "HELLO", 5));
sleep(5);
if(close(fd) != 0){
warn("Could not close write fd");
}
Run Code Online (Sandbox Code Playgroud)
程序执行正常,"HELLO"被发送,但有一个问题.调用write()函数时似乎没有发送"HELLO",而是在文件描述符关闭时发送.我添加了上面的sleep(5)行来测试这个理论,果然,"HELLO"在程序执行后约5秒发送.如何在write()命令之后立即发送"HELLO"而不是close()?
编辑4:事实证明,这实际上只是TTY输入的一个限制; 没有具体的OCaml,Coq或Emacs引起的问题.
我正在使用Emacs中的Proof General进行Coq程序,我发现输入的错误太长了.如果coqtop通过Proof General 提交的区域包含超过1023个字符,则Proof General(虽然不是Emacs)在等待响应时挂起,并且*coq*缓冲区包含一个^G超过1023的每个字符的额外字符.例如,如果是1025个字符区域被发送到coqtop,然后*coq*缓冲区将以两个额外的字符结束^G^G.我无法继续过去文件中这一点,我必须杀死coqtop过程(具有C-c C-x或kill/ killall从终端).
关于这种限制的事情coqtop本身就产生了.如果生成一个1024个字符或更长的字符串并将其输入,例如通过运行
perl -e 'print ("Eval simpl in " . (" " x 1024) . "1.\n")' | coqtop
Run Code Online (Sandbox Code Playgroud)
一切正常.(同样,coqc工作正常.) 但是,如果我coqtop在终端中运行,我不能在一行上输入超过1024个字符,包括结束返回字符.因此,输入一个1023个字符的行然后点击返回工作; 但是在输入1024个字符后,点击任何键,包括返回(但不包括删除等),除了产生哔声之外什么都不做.事实证明ocaml(OCaml toplevel)具有相同的行为:
perl -e 'print ((" " x 1024) . "1;;")' | ocaml
Run Code Online (Sandbox Code Playgroud)
工作正常,但如果ocaml从终端运行,我不能在一行上输入超过1024个字符.由于我的理解是coqtop依赖于OCaml顶级(更明显的是在运行时coqtop -byte),我想这是一个相关的限制. …
有没有办法找到(甚至是最好的猜测)python中字符串的"打印"长度?例如'potaa\bto'是8个字符,len但在tty上只打印6个字符.
预期用途:
s = 'potato\x1b[01;32mpotato\x1b[0;0mpotato'
len(s) # 32
plen(s) # 18
Run Code Online (Sandbox Code Playgroud) 有没有办法在执行后发送类似"数据结束"的内容
echo "test" > /dev/tty1
为了获得"输入光标"回到"接收"终端(在这种情况下为tty1)?
背景:如果需要,请跳至问题部分
我正在研究测试设备的前端.前端的目的是使编写长测试脚本更容易.几乎只是让它们更具人性化和可写性.
该设备将使用Prologix GPIB-USB控制器进行测试(参见prologix.biz).我们在http://heliosoph.mit-links.info/gpib-on-debian-linux-the-easy-way/找到了一个教程,并完成了所有步骤,并且它有效!
由于我们还没有测试设备,我们想用openpty在Python中编写一个模拟器.我们确实有GPIB-USB控制器,而不是那些连接到它的东西.我让仿真器成为GPIB-USB的完美替代品.这意味着我将遵循"Debian上的GPIB ..."教程(上面)并获得我编程模拟器返回的输出.输入和输出的方式与教程只是读取和写入pty设备(即/ dev/pts/2)而不是tty(即/ dev/ttyUSB0)相同.
现在仿真器工作了,我们想要编写一个可以轻松编写脚本的前端.我们的目标是创建一种在调用函数时写入一堆命令的宏系统.
问题:使用模拟器和设备存在
我使用以下Python函数来读取,写入和打开tty/pty设备,但是如果我在bash中使用echo和cat,我得到的结果不一样.
tty = os.open(tty_path, os.O_RDWR)
os.read(tty, 100)
os.write(tty, "++ver")
Run Code Online (Sandbox Code Playgroud)
例如,我希望以下内容是等效的
$ cat < /dev/pty/2 & # According to the tutorial, this must be run in parallel
$ echo "++ver" > /dev/pty/2
Prologix GPIB Version 1.2.3.4 ...
Run Code Online (Sandbox Code Playgroud)
和
tty = os.open("/dev/pyt/2", os.o_RDWR)
os.read(tty, 100) # In separate Thread to be run in parallel
os.write(tty, "++ver") # in main thread
Run Code Online (Sandbox Code Playgroud)
输出是非常不同的,请解释为什么以及如何解决它.
完整代码在这里:http://pastebin.com/PWVsMjD7
我有一个Python脚本,用于使用Python子进程模块跨多个主机并行执行命令.它包装了SSH,基本上就这样调用:
output = subprocess.Popen(["/bin/env", env, "/usr/bin/ssh", "-t", "%s@%s" % (user, host), "--", command], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
Run Code Online (Sandbox Code Playgroud)
有效命令执行如下:
/bin/env TERM=$TERM:password /usr/bin/ssh -t "%s@%s" % (user, host), "--", command
Run Code Online (Sandbox Code Playgroud)
它工作正常,除了我得到一个间歇性错误,我的终端在运行脚本后搞砸了(丢失换行符).从命令行"重置"修复它,但我不确定这是怎么回事.我注意到有时在元组输出的第一项结尾处有一个"\ r \n",有时它不在那里.请参阅以下内容,特别是" Permission denied\r \n":
**** Okay output ****
[user@/home/user]# ./command.py hosts.lists "grep root /etc/shadow"
Running command "grep root /etc/shadow" on hosts in file "hosts.test"
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server1.example.com closed.\r\n')
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server2.example.com closed.\r\n')
[user@/home/user]#
**** Output causes terminal to not display newlines …Run Code Online (Sandbox Code Playgroud) ssh -t remotehost vim /tmp/x.txt
Run Code Online (Sandbox Code Playgroud)
我知道我可以运行如上所述的命令.
但我希望能够在远程计算机上运行任何本地bash代码.出于这个原因,我想调用远程'bash -s',以便可以处理任何本地bash代码.
ssh -t remotehost 'bash -s' <<< vim /tmp/x.txt
Run Code Online (Sandbox Code Playgroud)
但是,上面的例子显示"由于stdin不是终端,因此不会分配伪终端".有没有办法让ssh通过stdin获取本地bash代码并通过远程'bash -s'运行它?谢谢.
据我所知terminfo(5),kcuu1 应该是按下向上箭头时终端发送的序列。我从来没有见过除了^[[A(现在谈论cat,搞乱终端设置等)以外的任何东西。那么,鉴于我使用的终端(rxvt、gnome-terminal、iTerm)都默认为 TERM=xterm,为什么不是 kcuu1 \E[A?
我看到 cuu1是 \E[A,但是(再次从手册页),这是我应该发送到终端以移动光标的字符串,而不是终端发送给我的字符串。
顺便说一句,这是 OS X 的情况。
我在 Windows 10 上使用 Git Bash。我想导入一个 SQL 文件以在我的 PostGres 12 本地数据库中运行。我尝试了下面的
$ PGPASSWORD=$DB_PASSWORD psql -U${DB_USER} $DB_NAME < scripts/my-script.sql
stdin is not a tty
Run Code Online (Sandbox Code Playgroud)
当我查看数据库时,脚本尚未运行,这使我相信错误消息告诉了我原因,但我不确定它的含义或如何修复它。