Почему /usr/bin/test на 4Кб меньше, чем /usr/bin/[? +68


AliExpress RU&CIS



Пользователь с Reddit под ником mathisweirdaf поделился интересными наблюдениями:

 $ ls -lh /usr/bin/{test,[}
-rwxr-xr-x 1 root root 59K  Sep  5  2019 '/usr/bin/['
-rwxr-xr-x 1 root root 55K  Sep  5  2019  /usr/bin/test

[ и test должны быть псевдонимами друг друга, и все же между исполняющими их файлами из GNU coreutils наблюдается разница в 4Кб. Почему?

Во-первых, для всех, кого это удивило: да, существует /usr/bin/[. По этой теме у меня есть отдельная статья (англ.), но я все же коротко поясню:

Когда вы пишете if [ -e /etc/passwd ]; then .. эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем. Обычно она встроена в оболочку, но иногда может реализовываться через /usr/bin/[. Это объясняет многое из ее загадочного поведения, например, почему она чувствительна к пробелам: [1=2] оказывается не более валидно, чем ls-l/tmp.

Тем не менее откуда возникает разница в размере? Можно сравнить вывод objdump, чтобы увидеть, куда помещаются данные. Вот выдержка из objdump -h /usr/bin/[:

              size                                          offset
15 .text         00006e82  0000000000002640  0000000000002640  00002640  2**4
16 .fini         0000000d  00000000000094c4  00000000000094c4  000094c4  2**2
17 .rodata       00001e4c  000000000000a000  000000000000a000  0000a000  2**5

А вот objdump -h /usr/bin/test:

15 .text         000068a2  0000000000002640  0000000000002640  00002640  2**4
16 .fini         0000000d  0000000000008ee4  0000000000008ee4  00008ee4  2**2
17 .rodata       00001aec  0000000000009000  0000000000009000  00009000  2**5

Здесь мы видим, что сегмент .text (скомпилированный исполняемый код) на 1504 байта больше, в то время как .rodata (постоянные значения и строки) больше на 864 байта.

Суть в том, что увеличенный размер сегмента .text вынуждает его перемещаться из 8000 в 9000, пересекая границу размера страницы 0х1000 (4096) и, следовательно, смещая все другие сегменты на 4096 байтов. Именно эту разницу в размере мы и наблюдаем.

Единственное номинальное отличие между [ и test в том, что [ требует наличия ] в качестве заключительного аргумента. Проверка этого потребовала бы минимальное количество кода, так зачем все же используются те самые ~1500 байтов?

Поскольку сложно просматривать скомпилированные исполняемые файлы, я собрал копию coreutils и сравнил список функций в каждом:

$ diff -u <(nm -S --defined-only src/[ | cut -d ' ' -f 2-) <(nm -S --defined-only src/test | cut -d ' ' -f 2-)
--- /dev/fd/63      2021-02-02 20:21:35.337942508 -0800
+++ /dev/fd/62      2021-02-02 20:21:35.341942491 -0800
@@ -37,7 +37,6 @@
 D __dso_handle
 d _DYNAMIC
 D _edata
-0000000000000099 T emit_bug_reporting_address
 B _end
 0000000000000004 D exit_failure
 0000000000000008 b file_name
@@ -63,7 +62,7 @@
 0000000000000022 T locale_charset
 0000000000000014 T __lstat
 0000000000000014 t lstat
-0000000000000188 T main
+00000000000000d1 T main
 000000000000000b T make_timespec
 0000000000000004 d nslots
 0000000000000022 t one_argument
@@ -142,16 +141,10 @@
 0000000000000032 T umaxtostr
 0000000000000013 t unary_advance
 00000000000004e5 t unary_operator
-00000000000003d2 T usage
+0000000000000428 T usage
 0000000000000d2d T vasnprintf
 0000000000000013 T verror
 00000000000000ae T verror_at_line
-0000000000000008 D Version
-00000000000000ab T version_etc
-0000000000000018 T version_etc_ar
-000000000000042b T version_etc_arn
-000000000000002f R version_etc_copyright
-000000000000007a T version_etc_va
 000000000000001c r wide_null_string.2840
 0000000000000078 T x2nrealloc
 000000000000000e T x2realloc

Главные участники – это функции version_etc*. Что они делают?

Давайте посмотрим:

/* The three functions below display the --version information the
   standard way [...]

Это 260 строк развернутых, интернационализированных, условных способов форматирования данных, которые составляют вывод --version. Все вместе они занимают около bc <<< "ibase=16; 7A+2F+42B+18+AB+8+99" = 1592 байтов.

Что это значит? Все просто. Дополнительные 4Кб уходят вот на что:

$ /usr/bin/[ --version
[ (GNU coreutils) 8.30
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Kevin Braunsdorf and Matthew Bradburn.

[ --version недостает заключительной ], поэтому вызов оказывается недействительным, и результат определяется реализацией. GNU спокойно позволяет вывести информацию о версии.

Тем временем /usr/bin/test --version оказывается действительным вызовом, и POSIX предписывает, чтобы она возвращала успех, когда первый параметр (--version) является непустой строкой.

Эта разница даже упоминается в документации:

Примечание: [ отвечает за опции --help и --version, а test нет.
test рассматривает каждую из них просто как непустую строку.

Загадка разгадана!

(Задачка: каковы будут последствия, если вопреки POSIX test будет поддерживать --help и --version?)




Комментарии (33):

  1. Serge78rus
    /#22965774

    В Debian разница не 4, а 8 К

    serge78rus@pcdeb:~$ ls -lh /usr/bin/{test,[}
    -rwxr-xr-x 1 root root 59K фев 28  2019 '/usr/bin/['
    -rwxr-xr-x 1 root root 51K фев 28  2019  /usr/bin/test

    • ZyXI
      /#22965854

      В моей Gentoo округлённые до КиБ размеры совпадают с вашими. Должно быть связано либо с версией coreutils (у меня — 8.32), либо с разрядностью системы (64).

      • Aldrog
        /#22965934

        Arch Linux, amd64, coreutils 8.32


        -rwxr-xr-x 1 root root 59K Mar  6  2020 '/usr/bin/['
        -rwxr-xr-x 1 root root 55K Mar  6  2020  /usr/bin/test

        • rogoz
          /#22971100

          Arch Linux, armv7l, coreutils 8.32-1

          -rwxr-xr-x 1 root root 42K апр  2  2020 '/usr/bin/['
          -rwxr-xr-x 1 root root 42K апр  2  2020  /usr/bin/test

    • 3vi1_0n3
      /#22967118

      Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем.

      А в bash будет использоваться внутренняя команда
      $ help [
      [: [ аргумент... ]
          Расчёт условного выражения.
          
          Это синоним встроенной команды test, но последним аргументом должна
          быть скобка «]», соответствующая открывающей «[».

      встроенной команды test

      • saboteur_kiev
        /#22969368 / +1

        это и имелось ввиду, что это отдельная команда (пусть и встроенная), но не синтаксис оболочки.
        Синтаксис оболочки это например cmd; cmd или cmd && cmd — в этом плане; и && — синтаксис оболочки.
        А [ ] — это оператор test

  2. arheops
    /#22965868

    А в centos 7 они почему-то обе сильно меньше.

    [root@pro-sip modules]# ls -l /usr/bin/{\[,test} 
    -rwxr-xr-x 1 root root 41488 Nov 16 23:24 /usr/bin/[
    -rwxr-xr-x 1 root root 37336 Nov 16 23:24 /usr/bin/test
    


    coreutils.x86_64 8.22-24.el7_9.2
    Возможно, не делают что-то добавленное между 8.22 и 8.30

  3. saboteur_kiev
    /#22965932 / +1

    [1=2] оказывается не более валидно, чем ls-l/tmp.

    так test1=2 тоже невалиден, а это более прямой пример

    • khim
      /#22969808 / -2

      Кто вам суказал, что test1=2 невалиден?

      Абсолютно валидная конструкция, хотя, возможно, делающая не то, чего вы хотели.

      P.S. А ведь комментарий заплюсован… уже и на Хабре люди перестали думать и перешли на подход TikTok-поколения?

      • dlinyj
        /#22969926 / +2

        Валидный [фр. valide — важный, действующий] — действительный, действенный, соответствующий требованиям.


        В данном случае у нас идёт спор терминологии. Что вы вкладываете в валидность и невалидность?

        • khim
          /#22969976 / -1

          Смотрим контекст статьи:

          Когда вы пишете if [ -e /etc/passwd ]; then .. эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем. Обычно она встроена в оболочку, но иногда может реализовываться через /usr/bin/[. Это объясняет многое из ее загадочного поведения, например, почему она чувствительна к пробелам: [1=2] оказывается не более валидно, чем ls-l/tmp.

          Таким образом валидность здесь понимается в контексте конструкций командной оболочки Unix.

          В этом контексте конструкция test1=2 — вполне валидно:
          $ if test1=2 ; then echo "Valid!" ; else echo "Invalid" ; fi
          Valid!
          

          В отличие от упомянутого в статье примера ls-l/tmp:
          $ if [1=2] ; then echo "Valid!" ; else echo "Invalid" ; fi
          bash: 1: command not found
          Invalid
          $ if ls-l/tmp ; then echo "Valid!" ; else echo "Invalid" ; fi
          bash: ls-l/tmp: No such file or directory
          Invalid
          


          Но разбираться — это ж думать нужно. А заминусовать — это проще.

          • saboteur_kiev
            /#22971560

            Кто вам суказал, что test1=2 невалиден?

            Я говорю. Она делает не то, что мне нужно.

            В отличие от упомянутого в статье примера ls-l/tmp:


            Ну так кто мешает вам сделать несуществующую команду существующей?
            $ if ls-l/tmp ; then echo "Valid!" ; else echo "Invalid" ; fi
            Я совершенно валидная команда, понял?
            Valid!

            Подсказать что нужно сделать?

            Но разбираться — это ж думать нужно. А заминусовать — это проще.

            Вот именно, нужно разбираться, а не придираться к выдумкам.

            • khajiit
              /#22984718 / -1

              Кто вам суказал, что test1=2 невалиден?
              Она делает не то, что мне нужно.

              Nuff said.

  4. bitterman
    /#22966056 / +1

    А в исходники нельзя было смотреть? Всё-таки, свободное ПО…

    • ironlion
      /#22966166

      Обе собираются из файла test.c, разница в:

        if (LBRACKET)
          {
            /* Recognize --help or --version, but only when invoked in the
               "[" form, when the last argument is not "]".  Use direct
               parsing, rather than parse_long_options, to avoid accepting
               abbreviations.  POSIX allows "[ --help" and "[ --version" to
               have the usual GNU behavior, but it requires "test --help"
               and "test --version" to exit silently with status 0.  */
            if (margc == 2)
              {
                if (STREQ (margv[1], "--help"))
                  usage (EXIT_SUCCESS);
      
                if (STREQ (margv[1], "--version"))
                  {
                    version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
                                 (char *) NULL);
                    test_main_return (EXIT_SUCCESS);
                  }
              }
            if (margc < 2 || !STREQ (margv[margc - 1], "]"))
              test_syntax_error (_("missing %s"), quote ("]"));
      
            --margc;
          }
      

      coreutils 8.32

  5. funca
    /#22966242

    -rwxr-xr-x 1 root root       59888 дек  5 23:55 test
    -rwxr-xr-x 1 root root       59888 дек  5 23:55 [

    ubuntu 21.04, coreutils 8.32-4ubuntu2

  6. begemoth3663
    /#22966322 / +4

    Во-истину BSD-системы проще:


    $ ls -li /bin/test /bin/[
    72389 -r-xr-xr-x  2 root  wheel  12408 14 Apr 18:08 /bin/[
    72389 -r-xr-xr-x  2 root  wheel  12408 14 Apr 18:08 /bin/test
    $ doas ldd /bin/test
    /bin/test:
        libc.so.7 => /lib/libc.so.7 (0x800247000)
    $ uname -srm
    FreeBSD 13.0-RELEASE amd64

  7. rezdm
    /#22966404 / +1

    Ради интереса, freebsd:

    [rezdm@rezdm-srv /bin]$ ls -al [ test
    -r-xr-xr-x  2 root  wheel  23672 Nov  1  2019 [
    -r-xr-xr-x  2 root  wheel  23672 Nov  1  2019 test
    [rezdm@rezdm-srv /bin]$ test --version
    [rezdm@rezdm-srv /bin]$ test --help
    [rezdm@rezdm-srv /bin]$ [ --version ]
    [rezdm@rezdm-srv /bin]$ [ --help ]
    [rezdm@rezdm-srv /bin]$ man [ | grep -i version
                       is retained for compatibility with previous versions of
         A test utility appeared in Version 7 AT&T UNIX.
    [rezdm@rezdm-srv /bin]$ man test | grep -i version
                       is retained for compatibility with previous versions of
         A test utility appeared in Version 7 AT&T UNIX.
    [rezdm@rezdm-srv /bin]$ uname -a
    FreeBSD rezdm-srv 12.1-RELEASE FreeBSD 12.1-RELEASE r354233 GENERIC  amd64
    

    • ZyXI
      /#22968006

      А в чём смысл запускать [ --… ] (с закрывающей скобкой) и test --…? В статье же написано, что второе работать и не должно (точнее, должно, но только как проверка пустоты строки), а второе может показывать help/version только потому что без закрывающей скобки команда некорректна.

      • rezdm
        /#22971038

        [rezdm@rezdm-srv ~]$ [ --version
        -bash: [: missing `]'
        [rezdm@rezdm-srv ~]$ [ --help
        -bash: [: missing `]'
        [rezdm@rezdm-srv ~]$ test -version
        [rezdm@rezdm-srv ~]$ test -help
        [rezdm@rezdm-srv ~]$ 
        

        • Aldrog
          /#22973998

          И это, кстати, тоже абсолютно ожидаемое поведение в bash независимо от системы (т.к. [ и test присутствуют в виде встроенных команд). Вот /usr/bin/[ --version в GNU/Linux выдаст справку.

        • Aldrog
          /#22974000 / +1

          del (бета-версия хабра комментарии дублирует)

  8. karavan_750
    /#22966758 / +3

    А еще бывает так, что coreutils скомпилены в единственный бинарник:

    Заголовок спойлера
    # ls -l $(realpath $(which {test,[}))
    -r-xr-xr-x 1 root root 1765416 Jan  1  1970 /nix/store/cc4nnlspm4pwmp5rvjl6wpy9nyzcsbnr-coreutils-8.31/bin/coreutils
    -r-xr-xr-x 1 root root 1765416 Jan  1  1970 /nix/store/cc4nnlspm4pwmp5rvjl6wpy9nyzcsbnr-coreutils-8.31/bin/coreutils

    • Antern
      /#22966924

      Очень сомневаюсь. Скорее, собраны в один пакет ( образ ).

      • karavan_750
        /#22968324

        Это coreutils из моей системы
        $ ls -l $(dirname $(realpath $(which [)))
        итого 1728
        lrwxrwxrwx 1 root root 9 янв 1 1970 '[' -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 b2sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 base32 -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 base64 -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 basename -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 basenc -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 cat -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 chcon -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 chgrp -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 chmod -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 chown -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 chroot -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 cksum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 comm -> coreutils
        -r-xr-xr-x 1 root root 1765416 янв 1 1970 coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 cp -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 csplit -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 cut -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 date -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 dd -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 df -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 dir -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 dircolors -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 dirname -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 du -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 echo -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 env -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 expand -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 expr -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 factor -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 false -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 fmt -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 fold -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 groups -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 head -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 hostid -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 id -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 install -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 join -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 kill -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 link -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 ln -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 logname -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 ls -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 md5sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 mkdir -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 mkfifo -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 mknod -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 mktemp -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 mv -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 nice -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 nl -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 nohup -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 nproc -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 numfmt -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 od -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 paste -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 pathchk -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 pinky -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 pr -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 printenv -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 printf -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 ptx -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 pwd -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 readlink -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 realpath -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 rm -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 rmdir -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 runcon -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 seq -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sha1sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sha224sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sha256sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sha384sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sha512sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 shred -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 shuf -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sleep -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sort -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 split -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 stat -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 stdbuf -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 stty -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sum -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 sync -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tac -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tail -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tee -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 test -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 timeout -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 touch -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tr -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 true -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 truncate -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tsort -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 tty -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 uname -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 unexpand -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 uniq -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 unlink -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 uptime -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 users -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 vdir -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 wc -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 who -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 whoami -> coreutils
        lrwxrwxrwx 1 root root 9 янв 1 1970 yes -> coreutils

    • arheops
      /#22967328 / +1

      А в busybox все вообще в один файл скомпилено, и что?

  9. user52523
    /#22968032 / +2

    Хм, всегда думал что [ это симлинк на test

    • telpos
      /#22969612

      Тоже думал, пока не попробовал заменить [ на test в скрипте

      • maxzhurkin
        /#22970966

        Это вообще не аргумент (контраргумент — busybox в Linux и rescue (аналог busybox) в BSD)

  10. maxzhurkin
    /#22970932

    Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем
    Это, конечно, так, но не всегда — зависит от конкретной оболочки

  11. technic93
    /#22977572

    Перевод не очень.


    Поскольку сложно просматривать отделенные исполнительные файлы, я создал собственную копию coreutils и сравнил список функций в каждом:

    Тут stripped binaries превратились в отдельные файлы, а простая компиляция (built) в создание своей утилиты.