Systemd

如何從 FIFO 套接字進行服務讀取

  • December 22, 2016

因此,在我拿起斧頭摧毀我的桌面之前,我會嘗試在這裡詢問:-)

我有一個名為 command.service 的套接字啟動服務。由於簡單起見,我只想將裸字元串或字元推送到此服務。

所以我有一個commander.socket 文件:

[Socket]
ListenFIFO=/run/commander.sk

[Install]
WantedBy=sockets.target

然後我有一個 command.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

現在我希望我在那裡執行的腳本通過標準輸入接收這些字元串或字元。

腳本的程式碼是:

#!/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");

通常 stdout 應該與期刊交談,我也希望那裡的印刷會到達期刊。

所以現在的事情是:

當我做:

echo "1" > /run/commander.sk

正在啟動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.

這意味著列印永遠不會到達外界……當我更新某些內容並重新安裝應有的設置時,手動停止發生。

我知道當我在控制台中呼叫 command.pl 腳本時,它確實按預期工作。從 stin 中讀取內容並與標準輸出對話。

我也知道幾個小時前,當我對它應該如何工作有更多的誤解時,列印輸出確實到達了期刊……

而且我沒有做任何事情,這可能會改變標準輸出的位置。在此期間,我做的最重要的事情是弄清楚我很可能需要

StandardInput=socket

行,接收作為標準輸入的套接字。

因為我現在已經第二天與之抗爭了,把我的頭髮一直拉出來,開始對我的家具變得咄咄逼人^^任何幫助都會非常感激:-)

無論如何,目前程式碼在 atm 線上: https ://github.com/JhonnyJason/pull-deploy-commander-service

更新 使用時

StandardInput=socket
StandardOutput=journal

服務腳本就像永遠執行,但沒有在日誌上給我任何輸出。

評論這兩行不會導致從標準輸入中讀取任何內容,但我至少在日誌中有標準輸出。此外,服務會一次又一次地被啟動,直到 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.

所以我有一個commander.socket

$$ … $$
然後我有一個commander.service $$ … $$

……你正在用 Perl 編寫。

Perl 是您問題的根源。這與systemd無關。所有這些與你正在做的單位設置有關的事情都是無關緊要的,除了你必須指定或編寫的服務來使用文件描述符#3。StandardInput=socket

您的服務將其標準輸入連接到您的 FIFO,並將其標準輸出和錯誤連接到流套接字(/run/systemd/journal/stdout與日誌對話)。

因為您的標準輸入/輸出文件描述符不是終端設備,所以 Perl 既不是行緩衝也不是單元緩衝它們的 I/O;它正在完全緩衝它。

當標準輸出不是終端設備時,沒有顯式地切換到單元緩衝(“autoflush”),而是某個地方(例如日誌)您希望在輸出發生時立即看到輸出,這是一個非常常見的 Perl 錯誤。

因此,通過使標準輸出“熱”/“自動刷新”來打開單元緩衝。

進一步閱讀

引用自:https://unix.stackexchange.com/questions/332077