- Команда test
- Проверка типа файла
- Сравнение строк
- Сравнение целых чисел
- Операции AND и OR
- Еще одно мнение о разнице между bin, sbin, usr/bin, usr/sbin
- /usr/bin
- /usr/sbin
- /usr/local/bin и /usr/local/sbin
- /home/$USER/bin
- Почему /usr/bin/test на 4Кб меньше, чем /usr/bin/[?
- Разница между bin, sbin, usr/bin, usr/sbin
- Почему /usr/bin/test на 4Кб меньше, чем /usr/bin/[?
- Comments 33
Команда test
Предназначена для проверки типа файла и сравнения чисел и строк. Возвращает код возврата 0 (истина) или 1 (ложь) в зависимости от вычисления выражения. Выражения могут быть как унарными, так и бинарными.
Для сокращения кода сценария используют парный оператор [ как синоним test . Парный оператор требует пробела между скобками потому, что [ (скобка) является командой оболочки.
Проверка типа файла
- -d file — истина, если file существует и является каталогом
- -e file — истина, если file существует
- -f file — истина, если file существует и является обычным файлом
- -r file — истина, если file существует и доступен для чтения
- -s file — истина, если file существует и имеет размер больше, чем ноль
- -w file — истина, если file существует и доступен для записи
- -x file — истина, если file существует и доступен для выполнения
- -L file — истина, если file существует и является символьной ссылкой
- file1 -nt file2 — истина, если file1 новее (дата модификации), чем file2
- file1 -ot file2 — истина, если file1 старее, чем file2
Сравнение строк
- -z string — истина, если длина string равна нулю
- -n string — истина, если длина string не ноль
- string1 = string2 — истина, если строки равны
- string1 != string2 — истина, если строки не равны
Сравнение целых чисел
- число1 -eq число2 — истина, если число1 равно число2
- число1 -gt число2 — истина, если число1 больше число2
- число1 -ge число2 — истина, если число1 больше или равно число2
- число1 -lt число2 — истина, если число1 меньше число2
- число1 -le число2 — истина, если число1 меньше или равно число2
- число1 -ne число2 — истина, если число1 не равно число2
Операции AND и OR
- expr1 -a expr2 — истина, если оба выражения expr1 и expr2 истина (операция AND)
- expr1 -o expr2 — истина, если хотя бы одно из выражений expr1 или expr2 истина (операция OR)
- ! expr — истина, если выражение expr ложно
В условном выражении команды test можно использовать круглые скобки, чтобы изменить порядок вычисления, но их нужно экранировать:
« [[…]] » — расширенный вариант от « […] », оболочка выполняет его как один элемент с кодом возврата. Внутри « [[…]] » разрешается выполнение операторов && , || которые приводят к ошибке в обычных скобках « […] ».
Источник
Еще одно мнение о разнице между bin, sbin, usr/bin, usr/sbin
Недавно я обнаружил вот такую статью: Разница между bin, sbin, usr/bin, usr/sbin. Хотелось бы поделиться своим взглядом на стандарт.
Содержит команды, которые могут использоваться как системным администратором, так и пользователями, но которые необходимы, когда не смонтированы никакие другие файловые системы (например, в однопользовательском режиме). Он также может содержать команды, которые косвенно используются скриптами.
Там ожидается присутствие таких команд:
Можно сделать симлинки на /usr, но хотя во времена systemd /usr на отдельном устройстве не встречается, его еще можно встретить на встраиваемой системе, светофоре, кофемолке и PDP-11 обслуживающем важный прибор в одной из лабораторий Академии Наук.
Утилиты, используемые для системного администрирования (и другие команды только для root), /sbin содержит двоичные файлы, необходимые для загрузки, восстановления, восстановления и/или восстановления системы в дополнение к двоичным файлам в /bin. Программы, выполняемые после того, как /usr монтируется (когда проблем нет), обычно помещаются в /usr/sbin. Локально установленные программы системного администрирования должны быть помещены в /usr/local/sbin.
fastboot, fasthalt, fdisk, fsck, getty, halt, ifconfig, init, mkfs, mkswap, reboot, route, swapon, swapoff, update.
Один из способов защиты системы от шаловливых рук юзеров — это запрет запуска этих утилит кому-попало, установкой атрибута x.
К тому же, замена /bin и /sbin на копии из архива (одинакового для всех однотипных систем) является быстрым способом починки систем без пакетного менеджера.
/usr/bin
Тут всё просто. Однотипные команды, одинаковые для всех серверов/кофемолок компании. И сам /usr может разворачиваться одинаковым для разных ОС (для /bin и /sbin такое как правило не работает), это архитектурно независимые программы. Может содержать линки на интерпретаторы perl или python, которые лежат в /opt или еще где-то в сети.
/usr/sbin
Тоже самое, что /usr/bin, но для использования только админами.
/usr/local/bin и /usr/local/sbin
Одна из важнейших локаций. В отличие от остального, /usr не может быть одинаковой для всей организации. Тут находятся ОС-зависимые, hardware-зависимые и просто программы, которые не на всех устройствах нужны. При синхронизации /usr на машинах, /usr/local требуется исключать.
/home/$USER/bin
Тут случай аналогичный с /usr/local, только лежат программы специфичные для конкретного пользователя. Можно переносить (или синхронизировать) на другую машину при переезде пользователя. То, что нельзя переносить складывается в /home/$USER/.local/bin. Можно использовать local без точки. /home/$USER/sbin по понятным соображениям отсутствует.
Источник
Почему /usr/bin/test на 4Кб меньше, чем /usr/bin/[?
Пользователь с Reddit под ником mathisweirdaf поделился интересными наблюдениями:
[ и test должны быть псевдонимами друг друга, и все же между исполняющими их файлами из GNU coreutils наблюдается разница в 4Кб. Почему?
Во-первых, для всех, кого это удивило: да, существует /usr/bin/[ . По этой теме у меня есть отдельная статья (англ.), но я все же коротко поясню:
Когда вы пишете if [ -e /etc/passwd ]; then .. эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем. Обычно она встроена в оболочку, но иногда может реализовываться через /usr/bin/[ . Это объясняет многое из ее загадочного поведения, например, почему она чувствительна к пробелам: [1=2] оказывается не более валидно, чем ls-l/tmp .
Тем не менее откуда возникает разница в размере? Можно сравнить вывод objdump, чтобы увидеть, куда помещаются данные. Вот выдержка из objdump -h /usr/bin/[ :
А вот objdump -h /usr/bin/test :
Здесь мы видим, что сегмент .text (скомпилированный исполняемый код) на 1504 байта больше, в то время как .rodata (постоянные значения и строки) больше на 864 байта.
Суть в том, что увеличенный размер сегмента .text вынуждает его перемещаться из 8000 в 9000 , пересекая границу размера страницы 0х1000 (4096) и, следовательно, смещая все другие сегменты на 4096 байтов. Именно эту разницу в размере мы и наблюдаем.
Единственное номинальное отличие между [ и test в том, что [ требует наличия ] в качестве заключительного аргумента. Проверка этого потребовала бы минимальное количество кода, так зачем все же используются те самые
Поскольку сложно просматривать скомпилированные исполняемые файлы, я собрал копию coreutils и сравнил список функций в каждом:
Главные участники – это функции version_etc* . Что они делают?
Это 260 строк развернутых, интернационализированных, условных способов форматирования данных, которые составляют вывод —version . Все вместе они занимают около bc .
Что это значит? Все просто. Дополнительные 4Кб уходят вот на что:
[ —version недостает заключительной ] , поэтому вызов оказывается недействительным, и результат определяется реализацией. GNU спокойно позволяет вывести информацию о версии.
Тем временем /usr/bin/test —version оказывается действительным вызовом, и POSIX предписывает, чтобы она возвращала успех, когда первый параметр ( —version ) является непустой строкой.
Эта разница даже упоминается в документации:
(Задачка: каковы будут последствия, если вопреки POSIX test будет поддерживать —help и —version ?)
Источник
Разница между bin, sbin, usr/bin, usr/sbin
Я заметил, что в busybox ссылки разложены по этим четырём директориям.
Есть ли какое-то простое правило, чтобы определить, в какой директории какая из ссылок должна лежать…
К примеру, kill лежит в /bin, а killall — в /usr/bin… Я не вижу никакой логики в таком разделении.
Вы, наверное, знаете, что Кен Томпсон и Дэннис Ритчи создали Unix на PDP-7 в 1969-ом. Так вот, примерно в 1971 они проапгрейдились до PDP-11 с парой дисков RK05 (по 1,5 мегабайта каждый).
Когда операционная система разрослась и перестала помещаться на первом диске (на котором была расположена корневая ФС), они перенесли часть на второй, где располагались домашние директории (поэтому точка монтирования называлась /usr — от слова user). Они продублировали там все необходимые директории ОС (/bin, /sbin, /lib, /tmp . ) и складывали файлы на новый диск, потому что на старом кончилось место. Потом у них появился третий диск, они примонтировали его в директории /home и перенесли туда домашние директории пользователей, чтобы ОС могла занять всё оставшееся место на двух дисках, а это были целых три мегабайта (огого!).
Разумеется, им пришлось ввести правило, что «когда операционная система загружается, она должна быть в состоянии примонтировать второй диск в директорию /usr, поэтому не надо класть программы типа mount на второй диск в /usr, а то получим проблему курицы и яйца». Вот так просто. И это относилось к Unix V6 35 лет назад.
Разделение /bin и /usr/bin (и всех подобных директорий) — это последствие тех событий, деталь реализации из 70-х, которая до сих пор, в течение десятилетий, копировалась бюрократами. Они никогда не задавали вопрос почему, они просто делали так. Это разделение перестало иметь смысл ещё до того, как Linux был создан, по нескольким причинам:
- При загрузке используется initrd или initramfs, который берёт на себя проблемы типа «этот файл нам нужен раньше чем тот». Таким образом, у нас уже есть временная файловая система, которая используется для загрузки всего остального.
- Разделяемые библиотеки (которые были добавлены в Unix ребятами из Berkley) не позволяют вам независимо менять содержимое /lib и /usr/lib. Эти две части должны соответствовать друг другу, иначе они не будут работать. Этого не происходило в 1974-ом, поскольку тогда у них была некоторая независимость из-за статической линковки.
- Дешёвые жёсткие диски преодолели барьер в 100 мегабайт где-то в 1990-ом и примерно в то же время появились программы для изменения размера разделов (partition magic 3.0 вышла в 1997-ом).
Разумеется, поскольку разделение есть, некоторые люди придумали правила, которые его оправдывают. Типа, корневой раздел нужен для всяких общих штучек ОС, а в /usr надо класть свои локальные файлы. Или в / помещают то, что распространяет AT&T, а в /usr — то, что твой дистрибутив, IBM AIX, или Dec Ultrix, или SGI Irix добавили, а в /usr/local лежат файлы, специфичные для твоей системы. А потом кто-то решил, что /usr/local — это не подходящее место, чтобы туда устанавливать новый софт, так что давайте ещё добавим /opt! Не удивлюсь, если появится ещё и /opt/local…
Разумеется, за 30 лет из-за такого разделения появлялись и исчезали всякие интересные специфичные для отдельных дистрибутивов правила. Например, «/tmp очищается при перезагрузке, а /usr/tmp — нет». (И в Ubuntu /usr/tmp нет в принципе, а в Gentoo /usr/tmp — это символическая ссылка на /var/tmp, на который теперь распространяется то правило, и он не очищается при перезагрузке. Да, это всё было ещё до tmpfs. А ещё бывает, что корневая ФС доступна только на чтение, и тогда в /usr тоже не надо ничего писать, а надо писать в /var. Или в / в основном нельзя писать, не считая того, что в /etc, которую иногда пытались перенести в /var. )
Бюрократы вроде Linux Foundation (которые поглотили Free Standards Group во время расширения годы назад) с радостью документируют и усложняют эти правила, даже не пытаясь понять, почему они появились. Они не догадываются, что Кен и Дэннис просто перенесли часть ОС в их домашнюю директорию, из-за того, что диск RK05 на PDP-11 был слишком мал.
Я практически уверен, что в busybox просто помещает файлы так же, как это исторически сложилось. Нет никакой реальной причины делать так до сих пор. Лично я просто делаю /bin, /sbin и /lib ссылками на аналогичные директории в /usr. Ведь люди, которые работают со встраиваемым софтом, стараются разбираться и упрощать…
Источник
Почему /usr/bin/test на 4Кб меньше, чем /usr/bin/[?
Comments 33
В моей Gentoo округлённые до КиБ размеры совпадают с вашими. Должно быть связано либо с версией coreutils (у меня — 8.32), либо с разрядностью системы (64).
Arch Linux, amd64, coreutils 8.32
Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем.
А в bash будет использоваться внутренняя команда
встроенной команды test
А в centos 7 они почему-то обе сильно меньше.
coreutils.x86_64 8.22-24.el7_9.2
Возможно, не делают что-то, добавленное между 8.22 и 8.30
[1=2] оказывается не более валидно, чем ls-l/tmp.
Кто вам суказал, что test1=2 невалиден?
Абсолютно валидная конструкция, хотя, возможно, делающая не то, чего вы хотели.
P.S. А ведь комментарий заплюсован… уже и на Хабре люди перестали думать и перешли на подход TikTok-поколения?
Валидный [фр. valide — важный, действующий] — действительный, действенный, соответствующий требованиям.
В данном случае у нас идёт спор терминологии. Что вы вкладываете в валидность и невалидность?
Когда вы пишете if [ -e /etc/passwd ]; then .. эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем. Обычно она встроена в оболочку, но иногда может реализовываться через /usr/bin/[ . Это объясняет многое из ее загадочного поведения, например, почему она чувствительна к пробелам: [1=2] оказывается не более валидно, чем ls-l/tmp .
Таким образом валидность здесь понимается в контексте конструкций командной оболочки Unix.
В этом контексте конструкция test1=2 — вполне валидно:
В отличие от упомянутого в статье примера ls-l/tmp :
Но разбираться — это ж думать нужно. А заминусовать — это проще.
Кто вам суказал, что test1=2 невалиден?
Я говорю. Она делает не то, что мне нужно.
В отличие от упомянутого в статье примера ls-l/tmp:
Ну так кто мешает вам сделать несуществующую команду существующей?
$ if ls-l/tmp ; then echo «Valid!» ; else echo «Invalid» ; fi
Я совершенно валидная команда, понял?
Valid!
Подсказать что нужно сделать?
Но разбираться — это ж думать нужно. А заминусовать — это проще.
Кто вам суказал, что test1=2 невалиден?
Она делает не то, что мне нужно.
Обе собираются из файла test.c, разница в:
Во-истину BSD-системы проще:
Ради интереса, freebsd:
А в чём смысл запускать [ —… ] (с закрывающей скобкой) и test —… ? В статье же написано, что второе работать и не должно (точнее, должно, но только как проверка пустоты строки), а второе может показывать help/version только потому что без закрывающей скобки команда некорректна.
И это, кстати, тоже абсолютно ожидаемое поведение в bash независимо от системы (т.к. [ и test присутствуют в виде встроенных команд). Вот /usr/bin/[ —version в GNU/Linux выдаст справку.
del (бета-версия хабра комментарии дублирует)
Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем
Перевод не очень.
Поскольку сложно просматривать отделенные исполнительные файлы, я создал собственную копию coreutils и сравнил список функций в каждом:
Тут stripped binaries превратились в отдельные файлы, а простая компиляция (built) в создание своей утилиты.
Источник