Approach 1 - readlink
- 1: STROUT
- 2: STRERR
文件描述符 1(STDOUT)/proc/[$PID]/fd/
,内核将此文件表示为指向文件描述符(FD)重定向到的文件的符号链接。
$ readlink -f /proc/[pid]/fd/[index]
/tmp/file
e.g.,
$ python sw.py
$ readlink -f /proc/29795/fd/1
/dev/pts/0
$ readlink -f /proc/29795/fd/2
/dev/pts/0
# Redirect strerr to test.log and strout to test2.log
$ python sw.py 2>test.log 1>test2.log
$ readlink -f /proc/29777/fd/2
/home/pi/Desktop/test.log
$ readlink -f /proc/29777/fd/1
/home/pi/Desktop/test2.log
Approach 2 - lsof
# Redirect strerr to test.log and strout to test2.log
$ python sw.py 2>test.log 1>test2.log
...
$ sudo lsof -p 29777
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
python3.8 29777 pi 0u CHR 136,0 0t0 3 /dev/pts/0
python3.8 29777 pi 1w REG 179,2 0 422946 /home/pi/Desktop/test2.log
python3.8 29777 pi 2w REG 179,2 0 422722 /home/pi/Desktop/test.log
这样,我们就知道 strout 和 strerr 被 redict 到哪里了。
如果不做任何 redirect,则会直接 output 到 terminal:
$ python sw.py
...
$ sudo lsof -p 29795
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
。。。
python3.8 29795 pi 0u CHR 136,0 0t0 3 /dev/pts/0
python3.8 29795 pi 1u CHR 136,0 0t0 3 /dev/pts/0
python3.8 29795 pi 2u CHR 136,0 0t0 3 /dev/pts/0
这时,值为/dev/pts/0
。
Approach - strace
$ strace -ttp 8233 -e write=1,2
strace: Process 8233 attached
23:51:45.049513 _newselect(0, NULL, NULL, NULL, {tv_sec=4, tv_usec=963316}) = 0 (Timeout)
23:51:50.018743 write(1, "111\n", 4) = 4
| 00000 31 31 31 0a 111. |
23:51:50.019113 clock_gettime(CLOCK_MONOTONIC, {tv_sec=789272, tv_nsec=248956742}) = 0
23:51:50.019751 _newselect(0, NULL, NULL, NULL, {tv_sec=10, tv_usec=0}) = 0 (Timeout)
23:53:03.491316 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
23:53:03.491605 sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
23:53:03.492670 write(2, "Traceback (most recent call last"..., 35) = 35
| 00000 54 72 61 63 65 62 61 63 6b 20 28 6d 6f 73 74 20 Traceback (most |
| 00010 72 65 63 65 6e 74 20 63 61 6c 6c 20 6c 61 73 74 recent call last |
| 00020 29 3a 0a ):. |
23:53:03.493302 write(2, " File \"sw.py\", line 5, in <modu"..., 36) = 36
| 00000 20 20 46 69 6c 65 20 22 73 77 2e 70 79 22 2c 20 File "sw.py", |
| 00010 6c 69 6e 65 20 35 2c 20 69 6e 20 3c 6d 6f 64 75 line 5, in <modu |
| 00020 6c 65 3e 0a le>. |
23:53:03.493864 openat(AT_FDCWD, "sw.py", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
23:53:03.494322 fstat64(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
23:53:03.494957 ioctl(3, TCGETS, 0xbec7b050) = -1 ENOTTY (Inappropriate ioctl for device)
23:53:03.495424 _llseek(3, 0, [0], SEEK_CUR) = 0
23:53:03.496024 fcntl64(3, F_DUPFD_CLOEXEC, 0) = 4
23:53:03.496392 fcntl64(4, F_GETFL) = 0x20000 (flags O_RDONLY|O_LARGEFILE)
23:53:03.496990 fstat64(4, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
23:53:03.497406 read(4, "import time\n\nwhile(True):\n pr"..., 4096) = 62
23:53:03.497868 close(4) = 0
23:53:03.498428 _llseek(3, 0, [0], SEEK_SET) = 0
23:53:03.498844 read(3, "import time\n\nwhile(True):\n pr"..., 8192) = 62
23:53:03.499478 close(3) = 0
23:53:03.499872 write(2, " time.sleep(10)\n", 19) = 19
| 00000 20 20 20 20 74 69 6d 65 2e 73 6c 65 65 70 28 31 time.sleep(1 |
| 00010 30 29 0a 0). |
23:53:03.500710 write(2, "KeyboardInterrupt\n", 18) = 18
| 00000 4b 65 79 62 6f 61 72 64 49 6e 74 65 72 72 75 70 KeyboardInterrup |
| 00010 74 0a t. |
23:53:03.501468 rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0xb6d2b120}, {sa_handler=0x5b5d0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0xb6d2b120}, 8) = 0
23:53:03.512529 sigaltstack(NULL, {ss_sp=0x11a7978, ss_flags=0, ss_size=16384}) = 0
23:53:03.513343 sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}, NULL) = 0
23:53:03.513860 rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0xb6d2b120}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0xb6d2b120}, 8) = 0
23:53:03.514448 getpid() = 8233
23:53:03.514884 kill(8233, SIGINT) = 0
23:53:03.515320 --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=8233, si_uid=1000} ---
23:53:03.517270 +++ killed by SIGINT +++