通过将字符串放入 tty 来构造命令

Ema*_*erg 17 io tty stdin

我设法做到了

echo -n "命令" > /dev/tty1

字母出现,光标移动,但它们是“幽灵”——如果你点击Enter,没有任何反应(它们不在标准输入中)。

编辑:

在下面屏幕截图的中间,你明白为什么我看到了这个的使用。(带有红色标题的行,就在带有黄色标题的行的正下方。)就像现在一样,您并没有真正“编辑”注释文本;你只是被要求写一个新的文本,它将替换你正在(不是真的)编辑的笔记的文本。因此,我认为可以通过简单地将旧文本粘贴到 tty 中来补救:如果用户点击 Enter,则不会进行任何修改。(该程序在 Perl/MySQL 中,但我认为寻求通用解决方案比“我如何在 Perl 中执行此操作”更有趣。)

例子

编辑2:

这是 Perl 代码,它使用下面的 C 代码(完全按预期工作),以及一个新的屏幕截图——希望这能澄清毫无疑问的事情:) 再次查看屏幕截图的中间,在那里进行了编辑到注释文本 - 这一次,旧文本在那里,例如,如果您只想修正错字,则不必重新键入整个注释文本。

my $edit_note_text = $edit_note_data[2];
print BOLD, RED, " new text: ", RESET;
system("writevt /dev/tty \"$edit_note_text\"");
my $new_text = <$in>;
$new_text = fix_input($new_text);
my $set_text = "UPDATE notes SET note = \"$new_text\" WHERE id = $edit_note_id";
$db->do($set_text);
Run Code Online (Sandbox Code Playgroud)

Better_example

Gil*_*il' 11

终端兼作两件事:输入设备(如键盘)和显示设备(如显示器)。当您从终端读取时,您会得到来自输入设备的信息。当您写入终端时,数据会进入显示设备。

没有强制输入到终端的通用方法。很少需要这样做。如果您需要与需要终端的程序进行交互,请使用专用终端模拟器(例如ExpectEmpty)或可编程终端包装器(例如ScreenTmux )。您可以使用 ioctl强制输入到 Linux 控制台。您可以使用xdotoolxmacro等工具强制输入到 X11 终端仿真器。


Sté*_*las 9

至少 Linux 和 BSD 有 TIOCSTI ioctl 将字符推回终端输入缓冲区(最多限制 [Linux 上的 4096 个字符]):

#include <sys/ioctl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>

void stackchar(char c)
{
  if (ioctl(0, TIOCSTI, &c) < 0) {
    perror("ioctl");
    exit(1);
  }
}
int main(int argc, char *argv[])
{
  int i, j;
  char c;

  for (i = 1; i < argc; i++) {
    if (i > 1) stackchar(' ');
    for (j=0; (c = argv[i][j]); j++) {
      stackchar(c);
    }
  }
  exit(0);
}
Run Code Online (Sandbox Code Playgroud)

编译它,并将其命名为:

cmd foo bar < "$some_tty"
Run Code Online (Sandbox Code Playgroud)

将字符推回某些 tty。

在 perl 中:

require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
Run Code Online (Sandbox Code Playgroud)

编辑:我现在意识到它与writevt解决方案中的 ioctl 相同。该命令的注释和名称具有误导性,因为 TIOCSTI 可用于任何终端,而不仅仅是 VT。


小智 7

我刚刚发现一个名为的小 C 程序writevt可以解决这个问题。在这里获取源代码。要使其编译,gcc只需先删除以下行:

#include <lct/cline.h>
#include <lct/utils.h>
Run Code Online (Sandbox Code Playgroud)

更新。该命令现在是console-tools的一部分,因此在更新的系统中可用,除非您的发行版使用kbd而不是console-tools,在这种情况下您可以从源代码编译它(更新的版本,无需修改)。

用法:

sudo writevt /dev/ttyN command 
Run Code Online (Sandbox Code Playgroud)

请注意,由于某种原因,您必须使用'\r'(或'\x0D') 而不是'\n'(或'\x0A') 来发送退货。


Bru*_*sky 5

在 Stack Overflow 上有一个更完整的演示

在python中你可以这样做:

import fcntl
import sys
import termios

with open('/dev/tty1', 'w') as fd:
    for char in "ls -la\n":
        fcntl.ioctl(fd, termios.TIOCSTI, char)
Run Code Online (Sandbox Code Playgroud)

这是假设使用 OP 指定的 tty 路径的简单"command"ls -la