我见过的大多数code samples都试图从没有本地回声的stdin读取。为此,他们修改"local modes"标记以删除setting to "Echo input characters"。我以为我可以修改"输入模式"标记为TIOCSTI
的{{3}}。但是,即使我以root身份运行脚本,它也没有任何效果。我写给fd的任何东西似乎都转到终端输出,而不是终端输入。基本上我想做的是"Insert the given byte in the input queue.",但是在纯python中。
"""
termfake.py
Usage: sudo python termfake.py /dev/ttys002
Get the tty device path of a different local termimal by running `tty`
in that terminal.
"""
import sys
import termios
fd = open(sys.argv[1], 'w')
fdno = fd.fileno()
# Returns [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
tatters = termios.tcgetattr(fdno)
print('original', tatters)
tatters[0] = termios.TIOCSTI
print('TIOCSTI', termios.TIOCSTI)
# Set iflag
termios.tcsetattr(fdno, termios.TCSANOW, tatters)
# Verify setting change
with open('/dev/ttys002', 'w') as fd2:
print('modified', termios.tcgetattr(fd2.fileno()))
fd.write('This is test\n')
fd.close()
答案 0 :(得分:6)
TIOCSTI
是一个ioctl(记录在tty_ioctl(4)
中),而非终端设置,因此您无法使用tcsetattr()
- 您需要提供假的每个字符改为输入ioctl()
。从来没有必要从Python做过ioctl,但以下似乎适用于在不同的终端中运行ls
(指定为参数,例如 / dev / pts / 13 )正在运行Bash:
import fcntl
import sys
import termios
with open(sys.argv[1], 'w') as fd:
for c in "ls\n":
fcntl.ioctl(fd, termios.TIOCSTI, c)
TIOCSTI
需要root权限(或CAP_SYS_ADMIN
更具体,但实际上通常在实践中相同) - 请参阅capabilities(7)
。
答案 1 :(得分:1)
我从@Ulfalizer那里得到了答案并将其扩展为一个完整且可用的应用程序。
import sys
import fcntl
import termios
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('tty', type=argparse.FileType('w'),
help='full tty path as given by the tty command')
group = parser.add_mutually_exclusive_group()
group.add_argument('-n', action='store_true',
help='prevent sending a trailing newline character')
group.add_argument('--stdin', action='store_true',
help='read input from stdin')
group = parser.add_argument_group()
group.add_argument('cmd', nargs='?',
help='command to run (required if not using --stdin)')
group.add_argument('args', nargs='*',
help='arguments to command')
args = parser.parse_known_args()
if args.stdin:
data = sys.stdin.read()
else:
data = ' '.join([args.cmd] + args.args)
for c in data:
fcntl.ioctl(args.tty, termios.TIOCSTI, c)
if not args.n and data[-1][-1] != '\n':
fcntl.ioctl(args.tty, termios.TIOCSTI, '\n')
以下是您使用它的方式:
终端#1:执行...
$ tty > /tmp/t1
终端#2:执行...
$ sudo python termfake.py $(cat /tmp/t1) date +%s
终端#1:观察......
$ tty > /tmp/t1
$ date +%s
1487276400