web-dev-qa-db-ja.com

bashスクリプトの「接続が拒否されました」エラーを取り除きます

私はこの行を持っています:

exec 3<>/dev/tcp/127.0.0.1/9091 > /dev/null 2>&1 ||  { PORT_IS_FREE="yes"; };

ポート9091が使用可能かどうかをチェックしています。接続できない場合、次のエラーが発生します。

my-script: connect: Connection refused
my-script: line 6: /dev/tcp/127.0.0.1/9091: Connection refused

もちろん、このエラーは悪いニュースではありません。ポートが空いていることを意味します。エラートレースがログに記録されないようにするにはどうすればよいですか? stdout/stderrを/ dev/nullに送信しようとしましたが、どうやらそれではうまくいきません。

ボーナス:

私が持っています set -eスクリプトの上部-接続が拒否されるとすべてが停止します-上記のような特定の行でエラーが予想される場合、どうすればその停止を防ぐことができますか?

だから私には2つの目標があります:

  1. エラーメッセージは予期されたものであり、ライブラリユーザーに表示する必要がないため、エラーメッセージを削除します。

  2. 予想どおりにエラーを無視します。可能であれば、set-eを使用します。

2
Alexander Mills

set -eを使い続けながら、既知のエラーを許可するには、次の呪文を使用します。

/bin/false || :

これは、||演算子を使用してエラーを「消費」し、set -eがアクティブな環境にとって致命的ではないと見なされるようにします。

すでに2>/dev/nullを使用して標準エラーを抑制しているので、ここで引用した行からエラーが発生していると確信していますか?また、execを使用するのではなく、より読みやすい代替手段として提案します。

if ! nc -z localhost 9091 1> /dev/null 2>&1; then
    port_free="yes"
fi

ncの戻りコードはifステートメントによってチェックされるため、これはset -eの後でも安全です。

2
DopeGhoti

エラーストリームと出力ストリームの両方を/ dev/nullに適切にリダイレクトし、それによってエラーメッセージを抑制するには、execコマンド全体をグループ化する必要があります。

{ exec 3<>/dev/tcp/127.0.0.1/9091; } > /dev/null 2>&1 || PORT_IS_FREE="yes"

execはShellに組み込まれているため、どのように動作するかを予測するのは難しいですが、<>を特別に処理できたとしても、操作全体が実行されると思います。いくつかのステップで、最後のストリームのみがリダイレクトされます。 execの働きについてもっと知っている人は、これにいくらかの光を当てることができるかもしれません。

編集:変数の割り当てに中括弧のグループ化が必要な理由は1つのコマンドなのでわかりませんが、必要に応じて、使用した裸の割り当ての代わりに、中括弧を例と組み合わせて使用​​できます。

エラーを無視する場合は、;を介して終了ステータスを使用する代わりに、||を使用してリダイレクト後にコマンドを終了できます。

{ exec 3<>/dev/tcp/127.0.0.1/9091; } > /dev/null 2>&1 ; PORT_IS_FREE="yes"

もちろん、この場合、他のエラーもキャッチできないという問題があります。試したところ、問題のエラーが発生した後の終了ステータスは1です。異なるエラーで他のコードが返される場合(1は非常に一般的なエラーコードであるため、実際には疑わしい)、1をテストできます。編集:このソリューションには、execの後にコード1が返されたときに終了しないという利点もあります。 、set -eが使用されている場合:

{ exec 3<>/dev/tcp/127.0.0.1/9091; } > /dev/null 2>&1 || [ "$?" = 1 ] && PORT_IS_FREE="yes"

それ以外の場合は、grepを使用してエラーメッセージを照合することができます。これは、私の意見ではより信頼性があります。

socketOpenOutput="$({ exec 3<>/dev/tcp/127.0.0.1/9091; } 2>&1`)"
socketOpenErrorCode="$?"
if [ "$socketOpenErrorCode" != 0 ]; then
    if ! echo "$socketOpenOutput" | grep 'connect\s*:\s*Connection refused' >/dev/null; then
        echo "An unexpected error happened when opening the socket!"
        exit 1
    fi
fi

PORT_IS_FREE="yes"

ただし、これはset -eではうまく機能しません。

1
Larry