完美包装器(在 Python 中)
Perfect Wrapper (in Python)
我运行一个调用/usr/bin/dpkg但不显示stdout/stderr的配置管理工具。
出了点问题,我想调试问题的根源。
我想查看对 dpkg
和 stdout/stderr 的所有调用。
我把原来的/usr/bin/dpkg
移到/usr/bin/dpkg-orig
,写了一个wrapper:
#!/usr/bin/env python
import os
import sys
import datetime
import subx
import psutil
cmd=list(sys.argv)
cmd[0]='dpkg-orig'
def parents(pid=None):
if pid==1:
return '\n'
if pid is None:
pid = os.getpid()
process = psutil.Process(pid)
lines = [parents(process.ppid())]
lines.append('Parent: %s' % ' '.join(process.cmdline()))
return '\n'.join(lines)
result = subx.call(cmd, assert_zero_exit_status=False)
with open('/var/tmp/dpkg-calls.log', 'ab') as fd:
fd.write('----------- %s\n' % (datetime.datetime.now()))
fd.write('%s\n' % parents())
fd.write('stdout:\n%s\n\n' % result.stdout)
sys.stdout.write(result.stdout)
fd.write('stderr:\n%s\n' % result.stderr)
fd.write('ret: %s\n' % result.ret)
sys.stderr.write(result.stderr)
sys.exit(result.ret)
现在我再次 运行 配置管理工具并搜索非零 "ret:" 行。
输出:
Parent: /usr/bin/apt-get -q -y -o DPkg::Options::=--force-confold -o DPkg::Options::=--force-confdef install openssl-foo-bar-aptguettler.cert
Parent: python /usr/bin/dpkg --force-confold --force-confdef --status-fd 67 --no-triggers --unpack --auto-deconfigure /var/cache/apt/archives/openssl-foo-bar-aptguettler.cert_1-2_all.deb
stdout:
stderr:
dpkg: error: unable to read filedescriptor flags for <package status and progress file descriptor>: Bad file descriptor
ret: 2
发生这种情况是因为我的包装器还不完美。
调用 dpkg
的工具想要读取文件描述符,但这不适用于我的包装器。
我的目标:
- 捕获对
dpkg
的所有调用并将其写入日志文件(有效)
- 写出父进程(有效)
dpkg
的父进程应该不会注意到差异并且不会像上面那样失败(还没有工作)。
知道如何实现吗?
我写了一个简单的 python 脚本来解决这个问题:
https://github.com/guettli/wrap_and_log_calls
Wrapper to log all calls to a linux command
particular use case: My configuration management tool calls
/usr/bin/dpkg. An error occurs, but unfortunately my configuration
management tool does not show me the whole stdout/stderr. I have no
clue what's wrong.
General use case: Wrap a linux command like /usr/bin/dpkg and write
out all calls to this.
我运行一个调用/usr/bin/dpkg但不显示stdout/stderr的配置管理工具。
出了点问题,我想调试问题的根源。
我想查看对 dpkg
和 stdout/stderr 的所有调用。
我把原来的/usr/bin/dpkg
移到/usr/bin/dpkg-orig
,写了一个wrapper:
#!/usr/bin/env python
import os
import sys
import datetime
import subx
import psutil
cmd=list(sys.argv)
cmd[0]='dpkg-orig'
def parents(pid=None):
if pid==1:
return '\n'
if pid is None:
pid = os.getpid()
process = psutil.Process(pid)
lines = [parents(process.ppid())]
lines.append('Parent: %s' % ' '.join(process.cmdline()))
return '\n'.join(lines)
result = subx.call(cmd, assert_zero_exit_status=False)
with open('/var/tmp/dpkg-calls.log', 'ab') as fd:
fd.write('----------- %s\n' % (datetime.datetime.now()))
fd.write('%s\n' % parents())
fd.write('stdout:\n%s\n\n' % result.stdout)
sys.stdout.write(result.stdout)
fd.write('stderr:\n%s\n' % result.stderr)
fd.write('ret: %s\n' % result.ret)
sys.stderr.write(result.stderr)
sys.exit(result.ret)
现在我再次 运行 配置管理工具并搜索非零 "ret:" 行。
输出:
Parent: /usr/bin/apt-get -q -y -o DPkg::Options::=--force-confold -o DPkg::Options::=--force-confdef install openssl-foo-bar-aptguettler.cert
Parent: python /usr/bin/dpkg --force-confold --force-confdef --status-fd 67 --no-triggers --unpack --auto-deconfigure /var/cache/apt/archives/openssl-foo-bar-aptguettler.cert_1-2_all.deb
stdout:
stderr:
dpkg: error: unable to read filedescriptor flags for <package status and progress file descriptor>: Bad file descriptor
ret: 2
发生这种情况是因为我的包装器还不完美。
调用 dpkg
的工具想要读取文件描述符,但这不适用于我的包装器。
我的目标:
- 捕获对
dpkg
的所有调用并将其写入日志文件(有效) - 写出父进程(有效)
dpkg
的父进程应该不会注意到差异并且不会像上面那样失败(还没有工作)。
知道如何实现吗?
我写了一个简单的 python 脚本来解决这个问题:
https://github.com/guettli/wrap_and_log_calls
Wrapper to log all calls to a linux command
particular use case: My configuration management tool calls /usr/bin/dpkg. An error occurs, but unfortunately my configuration management tool does not show me the whole stdout/stderr. I have no clue what's wrong.
General use case: Wrap a linux command like /usr/bin/dpkg and write out all calls to this.