Len*_*nny 2 perl systemd socket fifo
所以在我拿起斧头摧毁我的桌面之前,我会试着在这里问:-)
我有一个名为commander.service 的套接字激活服务。由于简单,我只想将裸字符串或字符推送到此服务。
所以我有一个commander.socket文件:
[Socket]
ListenFIFO=/run/commander.sk
[Install]
WantedBy=sockets.target
Run Code Online (Sandbox Code Playgroud)
然后我有一个commander.service文件:
[Unit]
Description=A service reading commands from the given socket
[Service]
ExecStart=/usr/bin/perl /root/commander.pl
StandardInput=socket
User=root
Group=root
Restart=no
[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)
现在我希望我在那里运行的脚本通过标准输入接收这些字符串或字符。
脚本的代码是:
#!/usr/bin/env perl
my $in = *STDIN;
my $out = *STDOUT;
$out->print("My printing reaches the outside world\n");
while($_ = <$in>) {
$out->print("Received: ");
$out->print($_);
$out->print("\n");
if($_ == "1") {
$out->print("I should run the command associated with 1 ;-) \n");
} elsif($_ == "2") {
$out->print("I should run the command associated with 2 ;-) \n");
} else {
$out->print("Oh! did someone just try to trick me?\n");
}
}
$out->print("And I'm gone!\n");
Run Code Online (Sandbox Code Playgroud)
由于通常标准输出应该与期刊交谈,我也希望那里的印刷能够到达期刊。
所以现在的事情是:
当我做:
echo "1" > /run/commander.sk
Run Code Online (Sandbox Code Playgroud)
正在激活commander.service,但是在日志中我只能看到日志:
Dez 22 03:18:25 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 03:31:32 phantom systemd[1]: Stopping A service reading commands from the given socket...
Dez 22 03:31:32 phantom systemd[1]: Stopped A service reading commands from the given socket.
Dez 22 03:31:41 phantom systemd[1]: Started A service reading commands from the given socket.
Run Code Online (Sandbox Code Playgroud)
这意味着打印永远不会到达外部世界......当我更新某些内容并按原样重新安装设置时,会手动停止。
我知道当我在控制台中调用 command.pl 脚本时,它确实按预期工作。从 stin 中读取内容并与 stdout 对话。
我也知道几个小时前,当我对它应该如何工作有更多误解时,打印输出确实到达了期刊......
据我所知,我没有做任何可能改变 stdout 去向的事情。在此期间我做的最重要的事情是弄清楚我很可能需要
StandardInput=socket
Run Code Online (Sandbox Code Playgroud)
行,接收套接字作为标准输入。
因为我现在正在与它斗争第二天并且一直拉我的头发并开始对我的家具变得咄咄逼人^^任何帮助都会非常感激:-)
无论如何,当前代码是 atm 在线:https : //github.com/JhonnyJason/pull-deploy-commander-service
更新 时使用
StandardInput=socket
StandardOutput=journal
Run Code Online (Sandbox Code Playgroud)
服务脚本就像永远主动运行,但没有在日志上给我任何输出。
注释这两行不会从标准输入读取任何内容,但我至少在日志中有标准输出。此外,该服务一次又一次地被激活,直到 systemd 拒绝重新启动它。
这是日志@04:05:58 运行时注释掉了这些行。@04:25:07 运行这些行
Dez 22 04:05:58 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 04:05:58 phantom perl[4687]: My printing reaches the outside world
Dez 22 04:05:58 phantom perl[4687]: And I'm gone!
Dez 22 04:05:58 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 04:05:58 phantom perl[4689]: My printing reaches the outside world
Dez 22 04:05:58 phantom perl[4689]: And I'm gone!
Dez 22 04:05:58 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 04:05:58 phantom perl[4691]: My printing reaches the outside world
Dez 22 04:05:58 phantom perl[4691]: And I'm gone!
Dez 22 04:05:58 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 04:05:58 phantom perl[4693]: My printing reaches the outside world
Dez 22 04:05:58 phantom perl[4693]: And I'm gone!
Dez 22 04:05:58 phantom systemd[1]: Started A service reading commands from the given socket.
Dez 22 04:05:58 phantom perl[4695]: My printing reaches the outside world
Dez 22 04:05:58 phantom perl[4695]: And I'm gone!
Dez 22 04:05:58 phantom systemd[1]: commander.service: Start request repeated too quickly.
Dez 22 04:05:58 phantom systemd[1]: Failed to start A service reading commands from the given socket.
Dez 22 04:05:58 phantom systemd[1]: commander.service: Unit entered failed state.
Dez 22 04:05:58 phantom systemd[1]: commander.service: Failed with result 'start-limit-hit'.
Dez 22 04:25:07 phantom systemd[1]: Started A service reading commands from the given socket.
Run Code Online (Sandbox Code Playgroud)
所以我有一个
commander.socket[...]
然后我有一个commander.service[...]
……而您正在使用 Perl 进行编写。
Perl 是您的问题所在。与 systemd 无关。所有这一切都摆弄单位设置你正在做的是无关紧要的,不同之处在于,你必须要么指定StandardInput=socket 或写你的服务,使用文件描述符#3。
您的服务的标准输入连接到您的 FIFO,其标准输出和错误连接到流套接字(/run/systemd/journal/stdout,与日志对话)。
因为你的标准输入/输出文件描述符不是终端设备,Perl 既不是行缓冲也不是单元缓冲它们的 I/O;它正在完全缓冲它。
没有明确地切换到单元缓冲(“自动冲洗”)时,标准输出不是终端设备,但它是某个地方(如日志),您想看到的输出,只要它发生,是一种很常见的Perl的错误。
因此,通过使标准输出“热”/“自动刷新”来打开单元缓冲。
$|. “perlvar”。 Perl 5 文档。perl.org。