86 linux gnu-screen stdin
我的 Linux 服务器上的屏幕会话中有一个长时间运行的服务器进程。它有点不稳定(遗憾的是不是我的软件,所以我无法修复它!),所以我想编写一个每晚重新启动该过程的脚本以帮助稳定性。让它正常关闭的唯一方法是转到 screen 进程,切换到它正在运行的窗口,并在其控制台上输入字符串“stop”。
我可以做任何智能重定向扭曲来让 cronjob 每天在固定时间发送该停止命令吗?
Cri*_*itu 96
这个答案并没有解决问题,但它留在这里是因为 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
Run Code Online (Sandbox Code Playgroud)
2 号航站楼:
[ciupicri@hermes ~]$ pidof cat
7417
[ciupicri@hermes ~]$ echo "shows on the tty but bypasses cat" > /proc/7417/fd/0
Run Code Online (Sandbox Code Playgroud)
Cri*_*itu 45
像这样启动服务器:
# screen -d -m -S ServerFault tr a-z A-Z # replace with your server
Run Code Online (Sandbox Code Playgroud)
screen将以分离模式启动,所以如果你想看看发生了什么,运行:
# screen -r ServerFault
Run Code Online (Sandbox Code Playgroud)
像这样控制服务器:
# 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
Run Code Online (Sandbox Code Playgroud)
(此答案基于将文本输入发送到来自Unix 和 Linux同级站点的分离屏幕)
参数说明:
Run Code Online (Sandbox Code Playgroud)-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.东西[字符串]
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
tmux将以分离模式启动,所以如果你想看看发生了什么,运行:
# tmux attach-session -t ServerFault
Run Code Online (Sandbox Code Playgroud)
像这样控制服务器:
# 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
Run Code Online (Sandbox Code Playgroud)
参数说明:
Run Code Online (Sandbox Code Playgroud)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.
mar*_*tbn 11
可以在不运行screen实用程序或任何其他花哨实用程序的情况下将输入文本发送到正在运行的进程。并且可以通过将此输入文本发送到进程的标准输入“文件”来完成/proc/PID#/fd/0。
但是,输入文本需要以特殊方式发送才能被进程读取。通过常规文件write方法发送输入文本不会导致进程接收文本。这是因为这样做只会附加到该“文件”,而不会触发进程读取字节。
要触发进程读取字节,必须对每个要发送的单个字节进行IOCTL类型操作TIOCSTI。这会将字节放入进程的标准输入队列。
此处将通过 C、Perl 和 Python 中的一些示例对此进行讨论:
——
因此,要回答大约 9 年前提出的原始问题,cron 作业需要运行一些类似于人们为其他问题编写的示例的小型实用程序脚本/程序,这会将字符串“stop\n”发送到该服务器进程在问题中,通过IOCTL类型为 的操作发送 5 个字节中的每一个TIOCSTI。
当然,这仅适用于支持TIOCSTI IOCTL操作类型的系统(如 Linux),并且仅适用于root用户帐户,因为这些“文件”下的“文件/proc/”归root.
小智 9
有一个更优雅的解决方案,可以避免使用tail -f浪费系统资源的永远循环。
首先创建一个命名管道来通过以下方式路由 STDIN:mkfifo /data/in。
然后阻止它进行写入,这样当您的进程读取所有当前内容时它就不会关闭:sleep infinity > /data/in &。永远休眠比这样要好,tailf -f /dev/null因为 tailf 使用 inotify 资源,并且每次某个应用程序向 /dev/null 发送数据时都会触发 tailf。您可以通过运行strace来看到这一点。它也比cat > /dev/null &本身cat与 STDIN 断开连接要好,而 STDIN 又会关闭/data/in。
/data/in使用提供的 STDIN:在后台启动您的进程application < /data/in &。这比使用尾部管道效果更好tail -f /data/in | application &,因为只有尾部停止时管道才会终止,但如果应用程序崩溃,管道将继续运行。
停止等待应用程序完成。wait $(pidof application)。这不使用任何资源,如果应用程序崩溃,您的代码将在等待后执行。如果您愿意,您可以在其周围添加应用程序重新启动循环。
要优雅地终止应用程序,请使用以下命令将系统信号转发给它:trap 'kill -SIGTERM $(pidof app)' SIGTERM
尝试这样开始:
# screen
# cd /path/to/wd
# mkfifo cmd
# my_cmd <cmd
C-A d
Run Code Online (Sandbox Code Playgroud)
还有这个要杀的:
# cd /path/to/wd
# echo "stop" > cmd
# rm cmd
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
117975 次 |
| 最近记录: |