プロセス(例: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以外のシステムにも移植可能です。