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
常にシェルなので、/dev/stdout
通常はパイプラインで動作します。ソケットを開くことを拒否しましたが、まだ同じ問題があります。
私が思いついた解決策は、tee
プロセスの置き換えを通じて置き換えることでした。
command1 | tee >(command2)
これはまだ完全に実現されていません。今、Bashは終了を待っていないからですcommand2
。この問題を解決するには、次の方法を使用できます。この他の答え:
{ { command1 | tee >(command2); } 3>&1 >&4 4>&- | cat; } 4>&1