그래서 도끼를 들고 데스크탑을 파괴하기 전에 여기에 물어보겠습니다 :-)
Commander.service라는 소켓 활성화 서비스가 있습니다. 단순성 때문에 이 서비스에는 문자열이나 문자만 푸시하고 싶습니다.
그래서 Commander.socket 파일이 있습니다.
[Socket]
ListenFIFO=/run/commander.sk
[Install]
WantedBy=sockets.target
그런 다음 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
이제 표준 입력을 통해 이러한 문자열이나 문자를 받기 위해 실행하는 스크립트를 원합니다.
이 스크립트의 코드는 다음과 같습니다.
#!/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");
일반적으로 표준 출력은 저널과 통신해야 하며, 그곳의 인쇄도 저널에 전달되기를 바랍니다.
이제 문제는 다음과 같습니다.
내가 할 때 :
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에서 읽고 stdout과 대화합니다.
나는 또한 그것이 어떻게 작동해야 하는지에 대해 더 많은 오해가 있었던 몇 시간 전에 인쇄물이 일지에 도착했다는 것도 알고 있습니다...
내가 아는 한, 나는 표준 출력이 가는 곳을 바꿀 수 있는 어떤 일도 하지 않습니다. 이 기간 동안 제가 한 가장 중요한 일은 나에게 가장 필요한 것이 무엇인지 파악하는 것이었습니다.
StandardInput=socket
라인은 소켓을 표준 입력으로 받습니다.
저는 지금 이틀 연속 이 문제와 싸우고 있기 때문에 계속해서 머리를 뽑고 가구에 대해 공격적으로 변하기 시작하세요 ^^ 어떤 도움이라도 매우, 매우 감사하겠습니다 :-)
어쨌든 현재 코드는 atm online입니다. https://github.com/JhonnyJason/pull-deploy-commander-service
고쳐 쓰다 그것을 사용할 때
StandardInput=socket
StandardOutput=journal
서비스 스크립트는 영원히 활발하게 실행되지만 로그에 어떤 출력도 제공하지 않습니다.
이 두 줄을 주석 처리하면 stdin에서 아무것도 읽히지 않지만 적어도 로그에는 stdout이 있습니다. 서비스는 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.
답변1
그래서 나는
commander.socket
[...] 을 가지고 있고 그 다음에는 [...]
를 가지고 있습니다.commander.service
...그리고 당신은 Perl로 글을 쓰고 있습니다.
Perl이 문제의 원인입니다. systemd와 아무 관련이 없습니다. 이 모든 것은 수행 중인 장치 설정과 관련이 없습니다.누구나지정하다StandardInput=socket
또는파일 설명자 #3을 사용하도록 서비스를 작성합니다.
서비스의 표준 입력은 FIFO에 연결되고, 표준 출력 및 오류는 스트림 소켓( /run/systemd/journal/stdout
, 로그와 통신)에 연결됩니다.
표준 입/출력 파일 설명자는 터미널 장치가 아니기 때문에 Perl은 I/O를 라인 버퍼링하거나 단위 버퍼링하지 않습니다.
표준 출력이 터미널 장치가 아닌 경우 장치 버퍼링("autoflush")에 대한 명시적인 전환은 없지만예출력이 발생하는 즉시 어딘가(예: 로그)를 보고자 하는 것은 Perl에서 흔히 저지르는 실수입니다.
따라서 stdout을 "hot"/"auto-refresh"로 만들어 셀 버퍼링을 활성화하십시오.
추가 읽기
- 브라이언 D. 포이.”출력 파일 핸들을 플러시/버퍼 해제하는 방법은 무엇입니까? 왜 내가 이 일을 해야 합니까?".펄 5 문서. perl.org.
$|
. "퍼발". 펄 5 문서. perl.org.- 마크 제이슨 도미나스(1998). "버퍼링으로 인해 어려움을 겪고 계시나요?". 펄 매거진. 플로버 홈페이지.