Неодинаковый формат вывода `df` в разных дистрибутивах Linux

Неодинаковый формат вывода `df` в разных дистрибутивах Linux

В 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являются относительно длинными строками. Он появляется dfв CentOSрешаетчтобы разделить свои записи на две строки, это нарушает логику, когда вы хотите более подробно проанализировать вывод.

В узких терминалах это может быть хорошей вещью, создавая полуколоночный вывод, понятный человеку, даже несмотря на ограниченное горизонтальное пространство. Я бы предпочел, чтобы этого не происходило при dfзаписи в не-tty (в вашем случае в конвейер).

Может быть dfв Ubuntu ведет себя аналогично, если записи в Filesystemстолбце длинные; возможно, вы просто не сталкивались с этим, потому что ваши записи относительно короткие. Я не знаю, это не важно. Важно то, что dfэто инструмент POSIX и он должен следоватьспецификация. Но в спецификации прямо указано:

Исторические dfреализации значительно различаются в своих выходных данных по умолчанию. Поэтому было необходимо описать выходные данные по умолчанию в свободной манере, чтобы учесть все известные исторические реализации и добавить переносимую опцию ( -P) для предоставления информации в переносимом формате.

О варианте:

-P
Выводить данные в формате, описанном в разделе STDOUT.

И, наконец, соответствующая часть раздела STDOUT (выделено мной):

Реализация может регулировать интервал между строкой заголовка и отдельными строками данных таким образом, чтобы информация была представлена ​​в упорядоченных столбцах.

Оставшийся выходс-Pдолжен состоять изодна строка информации для каждой указанной файловой системы. Эти строки должны быть отформатированы следующим образом:

"%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. В моем Debian 10 dfиз GNU coreutils возвращается к значению по умолчанию POSIX, когда POSIXLY_CORRECTустановлено в среде. Портативно вы можете принудительно использовать блоки размером 1024 байта с помощью -k.

Это переносимая команда, которая выдает (почти) пригодный для анализа вывод:

LC_ALL=POSIX df -Pk

Я думаю , что это почти поддается анализу, поскольку записи в Filesystemстолбце могут содержать пробелы; хотя в разумно настроенной ОС их нет.

Вы можете опустить LC_ALL=POSIXи все равно получить ожидаемые результаты, но в целом он должен быть там для разбора. Например, в моей польской локали ваш sed -e /^Filesystem/dне выполняет свою работу, потому что я получаю польский термин для "файловой системы" из моего df. LC_ALL=POSIXисправляет это. Все еще мойличныйпредпочтение не полагаться ни на что в заголовке. Я бы использовал sed 1dили tail -n +2; или делегировал задачу awk, поскольку awkуже находится в вашем конвейере. Это было бы:

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

Finally --exclude=не является портативным вариантом. По-видимому, он работает для вас в обеих рассматриваемых системах, хотя он может не работать в других системах.

Связанный контент