我想生成一个暂停的进程,可能是在另一个用户的上下文中(例如通过 sudo -u ...),为生成的进程设置一些 iptables 规则,继续运行该进程,并在该进程时删除 iptable 规则存在。
是否有任何标准方法(bash、corutils 等)可以让我实现上述目标?特别是,我怎样才能产生一个处于挂起状态的进程并获取它的 pid?
像这样编写一个包装脚本start-stopped.sh
:
#!/bin/sh
kill -STOP $$ # suspend myself
# ... until I receive SIGCONT
exec $@ # exec argument list
然后这样称呼它:
sudo -u $SOME_USER start-stopped.sh mycommand & # start mycommand in stopped state
MYCOMMAND_PID=$!
setup_iptables $MYCOMMAND_PID # use its PID to setup iptables
sudo -u $SOME_USER kill -CONT $MYCOMMAND_PID # make mycommand continue
wait $MYCOMMAND_PID # wait for its termination
MYCOMMAND_EXIT_STATUS=$?
teardown_iptables # remove iptables rules
report $MYCOMMAND_EXIT_STATUS # report errors, if necessary
然而,这一切都太过分了。您无需将进程置于暂停状态即可完成工作。只需制作一个包装脚本setup_iptables_and_start
:
#!/bin/sh
setup_iptables $$ # use my own PID to setup iptables
exec sudo -u $SOME_USER $@ # exec'ed command will have same PID
然后像这样称呼它
setup_iptables_and_start mycommand || report errors
teardown_iptables
您可以为您的程序编写一个 C 包装器,它将执行以下操作:
fork
并打印子 pid。exec
或运行您的原始程序system
。这行得通吗?
编辑:实际上您可以使用 shell 脚本执行上述过程。尝试以下 bash 脚本:
#!/bin/bash
echo "Pid is $$"
echo -n "Press Enter.."
read
exec $@
您可以将其运行为/bin/bash ./run.sh <your command>
我想您可以自己编写一个用于分叉的实用程序,其中分叉的子代在执行 exec 之前将自身挂起。否则,请考虑使用 LD_PRELOAD 库来执行您的“自定义”业务。
如果您关心确保安全,您可能应该看看更大的枪(使用 chroot,也许是半虚拟化,用户模式 linux 等);
最后提示:如果您不介意进行更多编码,ptrace 接口应该允许您执行您描述的操作(因为它用于实现调试器)
一种方法是gdb
在程序的主函数开始时登记暂停程序(使用命令“break main”)。这将保证进程足够快地挂起(尽管一些初始化例程可以在之前运行main
,但它们可能不会做任何相关的事情)。但是,为此,您需要为要启动的程序提供调试信息。
我建议你先手动尝试一下,看看它是如何工作的,然后弄清楚如何编写你所做的事情。
或者,可以在不使用 iptables 的情况下,使用 SELinux 或基于 ptrace 的工具(如 sydbox)来限制进程(如果这确实是您想要做的!)。