我的Linux服务器上的屏幕会话中有一个长时间运行的服务器进程。这有点不稳定(可惜不是我的软件,所以我无法解决这个问题!),所以我想编写一个每晚重启进程的脚本,以帮助稳定。使其正常关机的唯一方法是进入屏幕进程,切换至正在运行的窗口,然后在其控制台上输入字符串“ stop”。
我是否可以做任何智能重定向操作,以使cronjob每天在固定时间发送该stop命令?
我的Linux服务器上的屏幕会话中有一个长时间运行的服务器进程。这有点不稳定(可惜不是我的软件,所以我无法解决这个问题!),所以我想编写一个每晚重启进程的脚本,以帮助稳定。使其正常关机的唯一方法是进入屏幕进程,切换至正在运行的窗口,然后在其控制台上输入字符串“ stop”。
我是否可以做任何智能重定向操作,以使cronjob每天在固定时间发送该stop命令?
Answers:
这个答案不能解决问题,但是留在这里是因为30多个人发现它很有用,否则我很久以前就将其删除了。
写入/proc/*pid of the program*/fd/0
。在fd
子目录中包含的所有打开的文件的描述符和文件描述符0
是标准输入(1是stdout和2是标准错误)。
您可以使用它在运行程序的tty上输出消息,尽管它不允许您写入程序本身。
1号航站楼:
[ciupicri@hermes ~]$ cat
shows on the tty but bypasses cat
2号航站楼:
[ciupicri@hermes ~]$ pidof cat
7417
[ciupicri@hermes ~]$ echo "shows on the tty but bypasses cat" > /proc/7417/fd/0
ls -l /proc/7417/fd/0
。
/dev/pts/19
),y
字符无法到达应用程序本身。这类似于使用write(1)命令时发生的情况。无论如何,请尝试我的其他答案或图形自动化工具(如xdotool)。
像这样启动服务器:
# screen -d -m -S ServerFault tr a-z A-Z # replace with your server
屏幕将以分离模式启动,因此,如果要查看发生了什么,请运行:
# screen -r ServerFault
像这样控制服务器:
# screen -S ServerFault -p 0 -X stuff "stop^M"
# screen -S ServerFault -p 0 -X stuff "start^M"
# screen -S ServerFault -p 0 -X stuff "^D" # send EOF
(此答案基于将文本输入从Unix&Linux兄弟站点发送到分离的屏幕上的信息)
参数说明:
-d -m Start screen in "detached" mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts. -S sessionname When creating a new session, this option can be used to specify a meaningful name for the session. -r [pid.tty.host] -r sessionowner/[pid.tty.host] resumes a detached screen session. -p number_or_name|-|=|+ Preselect a window. This is useful when you want to reattach to a specific window or you want to send a command via the "-X" option to a specific window. -X Send the specified command to a running screen session e.g. stuff.
东西 [字符串]
Stuff the string string in the input buffer of the current window. This is like the "paste" command but with much less overhead. Without a parameter, screen will prompt for a string to stuff.
像这样启动服务器:
# tmux new-session -d -s ServerFault 'tr a-z A-Z' # replace with your server
tmux将以分离模式启动,因此,如果要查看发生了什么,请运行:
# tmux attach-session -t ServerFault
像这样控制服务器:
# tmux send-keys -t ServerFault -l stop
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault -l start
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault C-d # send EOF
参数说明:
new-session [-AdDP] [-c start-directory] [-F format] [-n window-name] [-s session-name] [-t target-session] [-x width] [-y height] [shell-command] Create a new session with name session-name. The new session is attached to the current terminal unless -d is given. window-name and shell-command are the name of and shell command to execute in the initial window. If -d is used, -x and -y specify the size of the initial window (80 by 24 if not given). send-keys [-lR] [-t target-pane] key ... (alias: send) Send a key or keys to a window. Each argument key is the name of the key (such as `C-a' or `npage' ) to send; if the string is not recognised as a key, it is sent as a series of characters. The -l flag disables key name lookup and sends the keys literally.
试试这个开始:
# screen
# cd /path/to/wd
# mkfifo cmd
# my_cmd <cmd
C-A d
并杀死:
# cd /path/to/wd
# echo "stop" > cmd
# rm cmd
echo "xxx" > cmd
一个程序将停止(因为管道将关闭)。尽管某些程序足够聪明,rewind(3)
当遇到EOF时可以重新打开它们的stdin。
可以在不运行screen
实用程序或任何其他实用程序的情况下将输入文本发送到正在运行的进程。可以通过将输入文本发送到流程的标准输入“文件”来完成/proc/PID#/fd/0
。
但是,需要以一种特殊的方式发送输入文本,以供过程读取。通过常规文件write
方法发送输入文本将不会导致进程接收文本。这是因为这样做只会附加到该“文件”,而不会触发进程读取字节。
要触发该过程以读取字节,必须对要发送的每个单个字节IOCTL
执行类型的操作TIOCSTI
。这会将字节放入进程的标准输入队列中。
这里用C,Perl和Python中的一些示例进行讨论:
-
因此,要回答将近9年前提出的原始问题,cron作业将需要运行一些小型实用程序脚本/程序,类似于人们为另一个问题编写的示例,它将向该服务器进程发送字符串“ stop \ n”在问题中,通过IOCTL
type 的操作发送5个字节中的每个字节TIOCSTI
。
当然,这仅适用于支持TIOCSTI
IOCTL
操作类型的系统(例如Linux),并且仅适用于root
用户帐户,因为这些“文件”由/proc/
拥有root
。
万一它对任何人
都有帮助:我有一个类似的问题,并且由于我使用的过程不在screen
or 之下tmux
,所以我不得不采用其他方法。
我附加gdb
了xterm
进程在其中运行的,并用于call write(5, "stop\n", 5)
从其gdb
写入主pty文件描述符。
我通过查找/proc/<pid>/fd
到/dev/ptmx
两个选项之间的链接,然后通过反复试验(将我的字符串发送到两个匹配的文件描述符似乎并没有造成伤害)来确定将数据发送至哪个文件描述符。
原来,xterm
我附加到的进程是spawn-new-terminal()
xterm
通过键绑定中的操作生成的,第二个ptmx
打开的文件描述符只是未关闭ptmx
的父xterm
进程的文件。
因此,尝试和错误调用已将输出发送到该另一个终端。
大多数xterm
进程没有两个ptmx
文件描述符。
这样可以有效地将字符串输入终端,然后将其发送到在其下运行的进程。
注意,您可能需要允许通过类似以下内容附加到正在运行的进程
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
由于我无法评论“克里斯蒂安·丘皮图(Cristian Ciupitu)(2010年)”这一最广为接受的答案,因此我不得不将其单独回答:
这个问题已经在以下线程中解决:https : //stackoverflow.com/questions/5374255/how-to-write-data-to-existing-processs-stdin-from-external-process
简而言之:
您必须使用stdin的管道启动进程,该管道在写入当前输入时不会阻塞也不关闭。这可以通过一个简单的无穷循环来实现,该循环将通过管道传递给相关进程:
$ (while [ 1 ]; do sleep 1; done) | yourProgramToStart
我可以确认,这与krissi打开在我的情况下不起作用的管道的方式不同。所示解决方案确实起作用了。
然后,您可以写入该进程的... / fd / 0文件以向其发送指令。唯一的缺点是,您还需要终止bash进程,该进程在服务器关闭后正在执行无限循环。