linux 在进程启动后使用命令行重定向进程的STDERR / STDOUT?

nwwlzxa7  于 2022-11-02  发布在  Linux
关注(0)|答案(8)|浏览(231)

在shell中,你可以做重定向,><,等等,但是在程序启动后呢?
我是这样问这个问题的,一个在我的终端后台运行的程序不断输出烦人的文本。这是一个重要的过程,所以我不得不打开另一个shell来避免文本。我希望能够>/dev/null或其他一些重定向,这样我就可以继续在同一个shell中工作。

wwwo4jvm

wwwo4jvm1#

除了关闭并重新打开tty(即注销并重新登录,这也可能会终止进程中的一些后台进程),您只剩下一个选择:

  • 使用gdb连接到相关进程,并运行:
  • (打开(“/dev/null”,0),1)
  • (打开(“/dev/null”,0),2)
  • 分离器
  • 退出

例如:

$ tail -f /var/log/lastlog &
[1] 5636

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog

$ gdb -p 5636
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Attaching to process 5636
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done.
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f3c8f5a66e0 (LWP 5636)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2

(no debugging symbols found)
0x00007f3c8eec7b50 in nanosleep () from /lib/libc.so.6

(gdb) p dup2(open("/dev/null",0),1)
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)]
$1 = 1

(gdb) p dup2(open("/dev/null",0),2)
$2 = 2

(gdb) detach
Detaching from program: /usr/bin/tail, process 5636

(gdb) quit

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null

您还可以考虑:

  • 使用screen;屏幕提供了几个虚拟TTY,您可以在它们之间进行切换,而不必打开新的SSH/telnet/etc会话
  • 使用nohup;这使您可以关闭和重新打开会话,而不会丢失...进程中的任何后台进程。
ngynwnxp

ngynwnxp2#

这将:

strace -ewrite -p $PID

它不是那么干净(显示的线条如下所示:write(#,<text you want to see>)),但工作!
您可能也不喜欢参数被缩写的事实。要控制这一点,请使用-s参数,该参数设置显示的字符串的最大长度。
它捕获所有流,因此您可能希望以某种方式对其进行过滤:

strace -ewrite -p $PID 2>&1 | grep "write(1"

仅显示描述符1调用。2>&1用于将STDERR重定向到STDOUT,因为默认情况下strace写入STDERR。

eqzww0vc

eqzww0vc3#

将输出从正在运行的进程重定向到另一个终端、文件或屏幕:

tty
ls -l /proc/20818/fd
gdb -p 20818

gdb 内:

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)
q

bash 终端分离一个正在运行的进程并使其保持活动状态:

[Ctrl+z]
bg %1 && disown %1
[Ctrl+d]

说明:

  • 20818-仅是运行进程PID的一个示例
  • p-打印gdb命令的结果
  • close(1)-关闭标准输出
  • /dev/pts/4-要写入的终端
  • close(2)-关闭错误输出
  • /tmp/myerrlog-要写入的文件
  • q-退出gdb
  • bg %1-在后台运行已停止的作业1
  • disown %1-从终端分离作业1
  • [Ctrl+z]-停止正在运行的进程
  • [Ctrl+d]-出口端子
gudnpqoy

gudnpqoy4#

引用弗拉德尔(和其他人)的优秀研究:
在同一个目录中创建以下两个文件,在您的路径中,例如$HOME/bin:
silence.gdb,包含(来自vladr的回答):

p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
detach
quit

和静音,包含:
第一个
现在,下次你忘记重定向火狐,例如,你的终端开始变得混乱与不可避免的“(firefox-bin:5117):Gdk-警告**:XID冲突,前方有故障”消息:

ps  # look for process xulrunner-stub (in this case we saw the PID in the error above)
silence 5117  # run the script, using PID we found

如果您不想看到gdb的输出,也可以将它重定向到/dev/null。

xytpbqjk

xytpbqjk5#

我不能直接回答你的问题,但这是我最近几天发现很有用的一个技巧:使用“screen”运行初始命令,然后断开连接。

2mbi3lxu

2mbi3lxu6#

这是基于以前答案的bash脚本部分,它在打开进程的执行过程中重定向日志文件,它在**logrotate**进程中用作postscript


# !/bin/bash

pid=$(cat /var/run/app/app.pid)
logFile="/var/log/app.log"

reloadLog()
{
    if [ "$pid" = "" ]; then
        echo "invalid PID"
    else
        gdb -p $pid >/dev/null 2>&1 <<LOADLOG
set scheduler-locking on
p close(1)
p open("$logFile", 1)
p close(2)
p open("$logFile", 1)
q
LOADLOG
        LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}')
        echo "log file set to $LOG_FILE"
    fi
}

reloadLog

已更新:对于gdb v7.11和更高版本,set scheduler-locking on或其他任何提到的here选项是必需的,因为在附加gdb之后,它不会停止所有正在运行的线程,并且由于文件使用,您可能无法关闭/打开日志文件。

7kqas0il

7kqas0il7#

Dupxis a simple *nix utility to redirect standard output/input/error of an already running process.

https://www.isi.edu/~yuri/dupx/

iqih9akk

iqih9akk8#

您可以使用重新导向(https://github.com/jerome-pouiller/reredirect/)。
型号

reredirect -m FILE PID

输出(标准和错误)将写入FILE。
reredirect自述文件还解释了如何恢复进程的原始状态,如何重定向到另一个命令或仅重定向到stdout或stderr。
reredirect还提供了一个名为relink脚本,该脚本允许重定向到当前终端:

relink PID
relink PID | grep usefull_content

(重定向似乎与另一个答案中描述的Dupx具有相同的功能,但它不依赖于Gdb)。

相关问题