另外在 Linux 有 reptyr 这个工具可以用。对 FreeBSD 只有有限的支持,还不能很好支持 macOS。
因为 macOS 用的是 lldb
,而且没有 procfs
,需要用 lsof
查看 fd
,所以我改写了一份脚本。
注意,受系统完整保护的预装软件,比如 bash
, tail
只有在关了 SIP 以后才能用这个方法处理。
(gdb
在 macOS 需要用 Keychain 签名才能用)
#
# fdswap
#
if [ "$2" = "" ]; then
echo "
Usage: $0 /path/to/oldfile /path/to/newfile [pids]
Example: $0 /var/log/daemon.log /var/log/newvolume/daemon.log 1234
Example: $0 /dev/pts/53 /dev/null 2345"; exit 0
fi
if lldb --version > /dev/null 2>&1; then true
else echo "Unable to find gdb."; exit 1
fi
src="$1"; dst="$2"; shift; shift
pids=$*
for pid in ${pids:=$( /sbin/fuser $src | cut -d ':' -f 2 )};
do
echo "src=$src, dst=$dst"
echo "$src has $pid using it"
# llbd 不接受 pipe 直接传脚本,可能我这里写错了 =_=
# 对 Bash 不太熟
lldb -b -o $(
echo "attach $pid"
echo 'call (int)open("'$dst'", 66, 0666)'
for ufd in $(LANG=C lsof -p $pid | \
grep "$src"\$ | awk ' { print $4; } ' | \
sed 's/.$//');
do echo 'call (int)dup2($0,'"$ufd"')'; done
echo 'call (int)close($0)'
echo 'detach'; echo 'quit'
)
done