異なる Linux ディストリビューションでは `df` からの出力形式が異なる

異なる Linux ディストリビューションでは `df` からの出力形式が異なる

Ubuntuではこのコマンドの出力は

df --exclude={tmpfs,devtmpfs,squashfs,overlay} | sed -e /^Filesystem/d | awk '{print $6 " " $1 " " $3 " " $4 " " $5}'

は:

/ /dev/mapper/dockerVG-rootLV 8110496 40591632 17%
/dockerssd /dev/mapper/ssdVG-ssdLV 214133656 274642488 44%
/dockerhdd /dev/mapper/hddVG-hddLV 83278236 1385191240 6%
/var/lib/docker /dev/mapper/hddVG-dockerLV 76046204 412729940 16%

それが私に必要なことです。

CentOS 6 では次の出力が得られます:

 /dev/mapper/vg_rproxy-lv_root
 51475068 43192316 12% /
/boot /dev/sda1 82688 379364 18%
 /dev/mapper/vg_rproxy-lv_home
 77349888 73119692 1% /home

めちゃくちゃだ。

CentOS 6 からの完全な出力:

$ df
Filesystem           1K-blocks    Used Available Use% Mounted on
/dev/mapper/vg_rproxy-lv_root
                      51475068 5661336  43192292  12% /
tmpfs                   957140       0    957140   0% /dev/shm
/dev/sda1               487652   82688    379364  18% /boot
/dev/mapper/vg_rproxy-lv_home
                      77349888  294352  73119692   1% /home

問題は何ですか? どうすれば解決できますか?

答え1

要約

使用df -P


完全な回答

/dev/mapper/vg_rproxy-lv_root/dev/mapper/vg_rproxy-lv_home比較的長い文字列です。CentOSdfでは決定するエントリを 2 行に分割すると、出力をさらに解析するときにロジックが壊れてしまいます。

狭い端末では、水平方向のスペースが限られている場合でも、半列化された人間が読める出力を作成するので、これは良いことかもしれません。df非 tty (この場合はパイプ) に書き込むときには、これが発生しないようにしたいと思います。

多分 dfUbuntuでは、Filesystem列のエントリが長い場合も同様に動作します。おそらく、列が比較的短いため、この問題が発生しなかっただけでしょう。わかりません。これは重要ではありません。重要なのは、dfPOSIXツールであり、従うべきであるということです。仕様しかし、仕様では次のように明確に述べられています。

これまでのdf実装では、デフォルトの出力がかなり異なっていました。そのため、既知のすべてのこれまでの実装に対応するために、デフォルトの出力を緩く記述し、-Pポータブル形式で情報を提供するためのポータブル オプション ( ) を追加する必要がありました。

オプションについて:

-P
STDOUT セクションで説明されている形式で出力を生成します。

そして最後に、STDOUT セクションの関連部分です (強調は筆者によるものです)。

実装では、情報が整然とした列に表示されるように、ヘッダー行と個々のデータ行の間隔を調整する場合があります。

残りの出力-Pで構成される指定されたファイルシステムごとに1行の情報これらの行は次のようにフォーマットされます。

"%s %d %d %d %d%% %s\n", <file system name>, <total space>,
    <space used>, <space free>, <percentage used>,
    <file system root>

したがって、dfを使用しない限り、 は何でも出力できます-P。 を使用しない場合、-Pの一部の実装dfでは予測可能で解析可能な出力が生成されますが、他の実装ではそれほどではありません。 それらの動作は十分に文書化されている場合とそうでない場合があります。したがって、一般に の出力を解析するときは、df常に を使用する必要があります-P

追加するだけで、-P特定の問題を解決するのに十分でしょう。

注: は-Pフォーマットのみを規定します。全体的な POSIX 仕様は POSIX ロケールにのみ適用されます。さらに、 の最近の実装では、dfデフォルトで 1024 バイトのブロックを使用する傾向がありますが、POSIX ではデフォルトは 512 と規定されています。 が環境に設定されている場合は、GNU coreutils の Debian 10 はdfPOSIX のデフォルトにフォールバックしますPOSIXLY_CORRECT。 を使用すると、移植可能な 1024 バイトのブロックを強制できます-k

これは、(ほぼ)解析可能な出力を生成するポータブル コマンドです。

LC_ALL=POSIX df -Pk

列のエントリにスペースが含まれる可能性があるため、ほぼ解析可能Filesystemだと思います。ただし、適切に構成された OS ではスペースは含まれません。

省略しLC_ALL=POSIXても期待通りの結果が得られるかもしれませんが、一般的には解析のためにそこにあるべきです。例えば、私のポーランド語ロケールでは、sed -e /^Filesystem/dmy から「ファイルシステム」のポーランド語の用語を取得するため、your は役に立ちませんdfLC_ALL=POSIXこの問題を修正します。個人的ヘッダー内のものには依存しないことをお勧めします。 または を使用するsed 1dか、 がすでにパイプライン内にあるため、tail -n +2にタスクを委任します。次のようになります。awkawk

LC_ALL=POSIX df -Pk --exclude={tmpfs,devtmpfs,squashfs,overlay} \
| awk 'NR>1 {print $6 " " $1 " " $3 " " $4 " " $5}'

Finally は--exclude=ポータブルなオプションではありません。どうやら、問題となっている両方のシステムでは動作するようですが、他のシステムでは動作しない可能性があります。

関連情報