iproute2 ss出力からリスニングTCPポートを抽出する

iproute2 ss出力からリスニングTCPポートを抽出する

プロセス(例:apache2)がリッスンしているポートを見つけ、この(tcp)ポート番号のみをfile1.txtファイルに印刷したいと思います。

  • 私が試したコマンドは次のとおりです。

    $ ss -atpln | grep 'apache2' | awk -F':' '{print $2}' > file1.txt
    
  • これは私の出力です(file1.txtで):

    80     *
    

私の出力が「*」ではなくポート番号(80)であることをどのように確認できますか?


OPに提供される重要な情報を追加するためにEd Mortonによって編集されましたコメント:

自分のシステムで次の順序をメモしてください。

$ ss -atpln | grep apache2

出力は次のとおりです

LISTEN 0 511 *:80 *:* users:(("apache2",pid=55338,fd=4),("apache2",pid=55337,fd=4),("apache2",pid=856,fd=4))

答え1

# ss -atpln | awk -F ':|[[:blank:]]+' '/apache2/ {print $5}'
443
443
443
80
80
80

コロンまたは1つ以上の「スペース」文字(スペースやタブなど)をフィールド区切り文字として使用します。これは、印刷したいフィールド(ポート番号)がフィールド5になりました。

grepすでに使用している場合は使用する必要はありませんawk。 awkはgrepの助けを借りずにパターンマッチングを完璧に実行できます。

sort -u固有のポート番号のみを印刷するには、出力をパイプで接続する必要があります。

しかし、出力例にそれぞれ443と80という3行がある理由がわからない場合は、私のシステムでは、apache2はポート80と443で3つの異なるIPアドレス(3つの異なる仮想ホスト用)を受信するように設定されています。*:80そして*:443

答え2

perl情報を抽出するために、より明示的な入力一致を使用して実行します。

ss -Otpln |
  perl -slne '
    print $1 if m{
      ^ LISTEN \s+ # State
        \d+ \s+    # Recv-Q
        \d+ \s+    # Send-Q
        (?: 0\.0\.0\.0 | \[::\] | \*) : (\d+) \s+ # source address on INADDR_ANY
                                                  # or INADDR6_ANY only
        \S+ \s+    # dest address
        users: .* \(" \Q$name\E ",pid # match on process name
      }x && ! $already_seen{$1}++' -- -name=apache2

あなたの出力形式が私の出力形式と異なります(私は0.0.0.0ワイルドカードIPv4アドレスを受け取り、[::]あなたはIPv6アドレスを受け取っています*)。これはss、出力フォーマットがそれほど安定していない可能性があることを意味します。代わりに、バッチ処理用のパターンを持ち、プロセス名で一致させることをss使用できます。lsof

lsof -Fn -wnMPa -c apache2 -i tcp -s tcp:listen |
  sed -n 's/^n\*://p' |
  sort -nu

また、Linux以外のシステムにも移植可能です。

関連情報