LTE 연결을 시작해야 하는 서비스를 작성 중입니다.
하지만 연결하는 데 사용하는 유틸리티(sakis3g)가 를 쓰고 있는데 /dev/stderr
, 이는 systemd에서는 사용할 수 없으며 로그가 가득 차 있습니다.
Cannot create /dev/stderr: No such device or address
이 문제를 해결할 방법이 있나요?
불행하게도 유틸리티 스크립트/바이너리를 변경하는 것은 선택 사항이 아닙니다.
편집: 이 서비스는 다음과 같습니다.
[Unit]
Description=LTE
After=syslog.target network-online.target
Before=openvpn-client@client
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mav/LTE/
ExecStartPre=/sbin/ip link set wwan0 down
ExecStart=/opt/mav/LTE/sakis3g connect -g --sudo
ExecStop=/opt/mav/LTE/sakis3g disconnect --sudo
[Install]
WantedBy=multi-user.target
그리고 이 상태에서 작동합니다. 그러나 더 자세한 디버그 출력 플래그로 시작하면 sakis3g
오류 가 -g
발생 stderr
합니다.
답변1
stderr이 없으면 오류가 표시되지 않습니다.
여기서 오류는 할 수 없다는 것입니다.열려 있는Linux에서 이 /dev/stderr
파일은 fd 2에서 열린 실제 파일에 대한 심볼릭 링크입니다(다른 시스템에서 /dev/stderr를 여는 것은 a를 실행하는 것과 같습니다 dup(2)
).
여기서 문제는 fd 2가 소켓(inet TCP, Unix 스트림 또는 기타)에서 열려 있고 open()
소켓 파일을 열 수 없다는 것입니다.
실행하는 경우:
sudo lsof -aU +E -d 2
사용 중인 시스템에서 systemd
대부분의 서비스에 대한 fd 2는 입니다 systemd-journald
.
해결 방법으로 다음과 같이 시작할 수 있습니다.
bash -o pipefail -c '{ /opt/mav/LTE/sakis3g connect -g --sudo 2>&1 >&3 3>&- | cat >&2 3>&-; } 3>&1'
즉, stderr를 cat
소켓이 아닌 파이프(to)로 만들고, cat
파이프에서 수신된 내용을 원래 stderr(소켓)로 전달하고, pipefail
이 옵션을 사용하여 명령의 종료 상태를 유지하는지 확인하십시오.
어쨌든 소스는 sakis3g
공개되어 있고sakis3g
초기화 파일정확히 다음을 수행하는 bash 스크립트입니다.
echo text >> /dev/stderr
바꾸다:
echo test >&2
> /dev/stderr
심지어 더 잘못된 것들도 있습니다 >> /dev/stderr
. tee -a /dev/stderr | other cmd
법적 용도가 없으며 /dev/stderr
소켓의 stderr과 작동하지 않으므로 수정하기 쉽습니다.
다음 주소로 문제를 제기하여 문제에 대해 알릴 수 있습니다.https://github.com/Trixarian/sakis3g-source/issues
답변2
tee
서비스 내에서 stdout을 수행하는 동안 비슷한 문제가 발생했습니다. 이것은 OP의 정확한 질문은 아니지만예또 다른 답변은 "공정 사용 /dev/stderr
"이라고 해서 나중에 누군가 필요할 경우를 대비해 여기에 게시할 가치가 있다고 생각했습니다.
즉, 나는 다음을 가지고 있습니다 :
command1 | tee /proc/$$/fd/1 | command2
이 경우 /proc/$$/fd/1
항상 shell 이므로 /dev/stdout
일반적으로 파이프라인에서 작동합니다. 소켓 열기를 거부했지만 여전히 동일한 문제가 있습니다.
내가 생각해낸 해결책은 tee
프로세스 대체를 통해 교체하는 것이었습니다.
command1 | tee >(command2)
이는 아직 완전히 실현되지 않았습니다., 이제 Bash는 종료를 기다리지 않기 때문입니다 command2
. 이 문제를 해결하기 위해 다음 방법을 사용할 수 있습니다.이 다른 답변:
{ { command1 | tee >(command2); } 3>&1 >&4 4>&- | cat; } 4>&1