我已经运行脚本好几天了。我将 stdout 重定向到$HOME/mylog
,但没有重定向 stderr ,因为我认为上面不会有任何内容。突然间,stderr 上开始出现数千行,所以我暂停了这项工作。有没有办法$HOME/myerr
从现在开始将 stderr 重定向到,而无需重新启动脚本?
我对盒子有 sudo 访问权限,它是 OS X。
也许使用 dtools 捕获的东西?
我不能丢失脚本迄今为止所做的工作并从头开始重新启动它。有没有办法在磁盘上“转储内存中的对象”,冻结程序,编辑变量(例如文件描述符)和恢复与新的背景?
答案1
我觉得如果把相关解释器的进程附加到gdb上是可以的。我用这个 perl 单行代码尝试过
perl -e 'do { print "x\n"; sleep(1) } while(1)'
它可以工作,但不幸的是不能使用类似的 bash 脚本。
首先,您必须找出要捕获其输出的进程的 PID。然后在另一个终端启动gdb
并执行以下 gdb 命令
attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID
之后写入的整个数据stderr
将重定向到/abs/olu/te/path/filename
,因为
attach PID
将进程附加到 gdb 并停止它call close(2)
关闭stderr
进程的文件描述符(stdout
文件描述符为1)call open(...)
打开一个新文件,并为新创建的文件描述符取最小的未使用整数,并且detach PID
继续该过程
至少在我的机器上是这样。前两行与 POSIX 兼容,但第三行不兼容。
第三行中的第二个和第三个参数open
记录在 中man 2 open
。在我的例子中,65 意味着open
应该创建文件并以只写方式打开文件,即O_WRONLY | O_CREAT
(在 中定义fcntl.h
)。第三个参数告诉 open 创建具有用户 ie 读写权限的文件S_IWUSR | S_IRUSR
(在 中定义sys/stat.h
)。所以也许你必须自己找出适合你机器的值。
答案2
这是一个粗略的答案,我希望其他人做得更好,但如果没有其他想法,请附加 gdb 并强制进程进行一些系统调用:
(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c