Gần đây đã gặp phải vấn đề này (thông qua một cách khác: Vim chạy trên một máy chủ từ xa và tôi đã quên màn hình), tôi quyết định tìm kiếm một cách.
Ý tưởng đầu tiên là tìm kiếm các mô tả tập tin được sử dụng bởi Vim và thử viết nó. Các fds của Vim trỏ đến psedoterminal được mở bởi trình giả lập thiết bị đầu cuối, đủ tự nhiên:
$ ls -l /proc/$(pgrep -n vim)/fd/
total 0
lrwx------ 1 muru muru 64 Nov 17 01:25 0 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 1 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 2 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 3 -> socket:[99564312]
Tuy nhiên, một vài lần thử đầu tiên của tôi đã thất bại:
echo '^[:wq^M' > /proc/$(pgrep -n vim)/fd/0
echo ':wq^M' > /proc/$(pgrep -n vim)/fd/0
echo ':wq^M' > /proc/$(pgrep -n vim)/fd/0
echo '^C' > /proc/$(pgrep -n vim)/fd/0
printf "%s" '^[:wqa!^M' > /proc/$(pgrep -n vim)/fd/0
Các ^[
và ^M
được thu được bởi CtrlVEscvà CtrlVEnter, tương ứng.
Tất cả đều dẫn đến các ký tự hiển thị trên thiết bị đầu cuối (Tôi đã thử nghiệm điều này cục bộ, trước khi áp dụng nó cho phiên từ xa). Googling xung quanh, tôi tìm thấy bài viết SO này , sử dụng Python để ghi vào thiết bị giả hành:
#!/usr/bin/python
import sys,os,fcntl,termios
if len(sys.argv) != 3:
sys.stderr.write("usage: ttyexec.py tty command\n")
sys.exit(1)
fd = os.open("/dev/" + sys.argv[1], os.O_RDWR)
cmd=sys.argv[2]
for i in range(len(cmd)):
fcntl.ioctl(fd, termios.TIOCSTI, cmd[i])
fcntl.ioctl(fd, termios.TIOCSTI, '\n')
os.close(fd)
Và thử nó trên một vỏ python tương tác đã làm việc:
$ sudo python3
Python 3.5.0 (default, Sep 20 2015, 11:28:25)
[GCC 5.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, fcntl, termios
>>> fd = os.open('/dev/pts/14', os.O_RDWR)
>>> a = '\033:wqa!\n'
>>> for i in a: fcntl.ioctl(fd, termios.TIOCSTI, i);
...
b'\x1b'
b':'
b'w'
b'q'
b'a'
b'!'
b'\n'
>>>
Làm xong!