子脚本可以将输出写入父进程吗?

子脚本可以将输出写入父进程吗?

我有一个通知脚本,每当 keepalived 守护进程的状态改变时就会启动该脚本。

问题是,当使用 -l(记录到本地控制台)选项运行 keepalived 时,显示的输出中没有出现我的通知脚本的 echo 输出

通常情况下,我可以将此输出写入文件,这将是一个很好的解决方案,但在这种情况下,keepalived 守护进程正在 docker 容器中运行,并且我希望 docker 守护进程查看所有输出的日志,包括来自我的通知脚本的输出。

这是我为通知脚本尝试过的操作:

#!/bin/bash

MY_PPID=$(ps -o ppid= $$)
MY_PPID=${MY_PPID// }

function echo
{
  builtin echo $(date +"%b %e %H:%M:%S"): $1 >> /proc/${MY_PPID}/fd/0
}

echo "Notify state=$3"

keepalived 的输出如下:

Starting VRRP child process, pid=8847
Interface queue is empty
No such interface, ib0
No such interface, ib1
No such interface, docker0
Interface queue is empty
No such interface, ib0
Registering Kernel netlink reflector
No such interface, ib1
No such interface, docker0
Registering Kernel netlink command channel
Registering gratuitous ARP shared channel
Registering Kernel netlink reflector
Initializing ipvs 2.6
Registering Kernel netlink command channel
Opening file '/etc/keepalived/keepalived.conf'.
Configuration is using : 5879 Bytes
Opening file '/etc/keepalived/keepalived.conf'.
Configuration is using : 61747 Bytes
Using LinkWatch kernel netlink reflector...
Using LinkWatch kernel netlink reflector...
VRRP_Instance(vip) Transition to MASTER STATE
VRRP_Instance(vip) Entering MASTER STATE
Opening script file /etc/keepalived/notify.sh

如果它有效的话,我期望看到一行额外的内容:

Notify state=MASTER

但显然它不起作用。有什么办法可以让它正常工作吗?


我认为我已经找到问题所在。MY_PPID 不再作为进程存在。执行脚本时,keepalived 进程似乎会执行双重 fork 来分离脚本。当我写入其中一个 keepalived 进程的 fd 时,它确实有效。我可以从文件 /var/run/keepalived.pid 中获取 pid。

我会尝试一下并报告结果。

答案1

为什么/proc/${MY_PPID}/fd/0?通常是控制台输出...

/proc/${MY_PPID}/fd/您能识别Supervisord 进程的日志文件吗?

答案2

事实证明,它不起作用,因为 keepalived 在调用子脚本的 exec 之前进行了双重 fork。因此 MY_PPID 不再是有效的进程 ID。

解决方案是使用/var/run/vrrp.pid文件获取正确的id。

这有效:

#!/bin/bash

TYPE=$1
NAME=$2
STATE=$3

# Get PID for keepalive
KA_PID=$(<"/var/run/vrrp.pid")

function echo
{
  # Send script output directly to keepalived
  builtin echo $(date +"%b %e %H:%M:%S"): "$0": $1 > "/proc/${KA_PID}/fd/1"
}


echo "$TYPE $NAME $STATE"

相关内容