「picom」がコマンドにあり、「ps」出力に表示されるため、「picom」のgrep psが失敗したときに正しく機能するpicom切り替え用のi3コマンド

「picom」がコマンドにあり、「ps」出力に表示されるため、「picom」のgrep psが失敗したときに正しく機能するpicom切り替え用のi3コマンド

私のi3設定には次の行があります。

bindsym $Super+Shift+F10 exec --no-startup-id ps aux | grep -q '[p]icom' && killall picom || picom

キーバインディングを押すと、シェルコマンドが実行されます(--no-startup-id以降のすべてはシェルコマンドです)。シェルコマンドを使用すると、デスクトップでPicomを使用して設定を切り替えることができました。コマンドを実行し、psを使用してすべてのプロセスのリストを取得し、grepを使用して「picom」を検索します。 grepが何かを見つけた場合はtrueを返し、Killallは実行中のすべてのpiccomを終了します。 grepが何も見つからない場合は、piccomを起動します。

ところで、問題は、コマンドに「picom」が2回でもあるため、grepが常にこれを確認してtrueを返す必要があるため、コマンドを常に実行する必要があることkillall picomです。

これが真であることを確認するために、teeを追加して、psの出力をlog1というファイルに書き込むようにコマンドを変更しました。

bindsym $Super+Shift+F10 exec --no-startup-id ps aux | tee log1 | grep -q '[p]icom' && killall picom || picom

cat log1 | grep picom上記のi3キーバインディングを使用した後、picomなしで実行したときの出力は次のとおりです。

ordici   19951  0.0  0.0   3192  2040 ?        Ss   17:24   0:00 /bin/sh -c ps aux | tee log1 | grep -q '[p]icom' && killall picom || picom

だから私は正しかった。 psの出力には、ピコムが実行されていなくてもピコムが含まれていました。それでは、このコマンドが完全に機能するのはなぜですか?

もう1つのことは、i3キーバインディングの代わりに端末でコマンドを実行し、ピコムが実行されていない場合はログにpsコマンドがないことです。しかし、予想通り、コマンドはまだ機能しています。

答え1

この問題について書いて、私はそれがなぜ動作するのか気づきました。私はこの記事を無駄に書かないようにとにかく投稿すると思いました。

grep picom私のシナリオでは、期待どおりの用量は常にtrueを返します。したがって、常に実行されますkillall picom。コマンドは次のようになります(これは私が今から使用します)。

killall picom || picom

動作する理由はkillall終了値もあるからです!終了する「picom」というプロセスが見つからない場合は、ゼロ以外のkillall終了値を返します。その後、失敗する前にコマンドに従ってpicomが実行されます!

したがって、両方grepまたはkillall失敗すると、picom元のコマンドで実行が実行される可能性があります。これがif文と「&&||」同じ論理演算子の違いです。論理演算子は、&&AND演算子()チェーン内の複数のコマンドが失敗し、OR演算子(||)をトリガします。

テストのために、元のコマンドをifステートメントに変更しました。

if ps aux | grep -q '[p]icom'; then
    killall picom
else
    picom
fi

そして、実行するかどうかを決定する唯一の要因はpicomの戻り値であり、この場合は常にtrueを返すため、コマンドは期待どおりに切り替えられません。killallpicomgrepgrep

答え2

実行されていない場合、自動的に失敗するのはなぜ面倒でps-inggrepですか?次のようにできそうです。picomkillall

killall picom || picom

コマンド結果(終了ステータス)のいくつかの条件付きテストは次のとおりです。

grep -q '[p]icom' && { killall picom; true; } || picom

if-elseを使用せずにこれを行う方法です。なぜなら今発見したように、a && b || cこれはそうではないからです。三項演算子つまり、これは次のことを意味しません。

if a; then
    b
else
    c
fi

これが意味するのは(es=終了状態)です:

a; es=$?
if (( es == 0 )); then
    b; es=$?
fi
if (( es != 0 )); then
    c; es=$?
fi
(exit $es)

バラよりbash if文と条件付き実行ロジック関連する回答は、上記の内容をより明確にするのに役立ちます。

関連情報