В коде «{exec> / dev / null; }> / dev / null », что происходит под капотом?

Хорошо, проблема решена путем выполнения этих команд и перезагрузки:

sudo modprobe -r acer_wmi
sudo rfkill unblock all
echo "blacklist acer_wmi" | sudo tee /etc/modprobe.d/acer-wmi.conf
15
21.12.2016, 02:28
3 ответа

Чтобы не использовать под-оболочку или под-процесс, когда вывод составного списка {} передается по трубопроводу >, оболочка сохраняет дескриптор STDOUT до запуска составного списка и восстанавливает его после. Таким образом, exec > в составном списке не переносит свое действие дальше точки, где старый дескриптор восстанавливается как STDOUT.

Давайте посмотрим на соответствующую часть strace bash -c '{ exec >/dev/null; } >/dev/null; echo hi' 2>&1 | cat -n:

   132  open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
   133  fcntl(1, F_GETFD)                       = 0
   134  fcntl(1, F_DUPFD, 10)                   = 10
   135  fcntl(1, F_GETFD)                       = 0
   136  fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
   137  dup2(3, 1)                              = 1
   138  close(3)                                = 0
   139  open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
   140  fcntl(1, F_GETFD)                       = 0
   141  fcntl(1, F_DUPFD, 10)                   = 11
   142  fcntl(1, F_GETFD)                       = 0
   143  fcntl(11, F_SETFD, FD_CLOEXEC)          = 0
   144  dup2(3, 1)                              = 1
   145  close(3)                                = 0
   146  close(11)                               = 0
   147  dup2(10, 1)                             = 1
   148  fcntl(10, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
   149  close(10)                               = 0

Вы видите, как в строке 134 дескриптор 1 (STDOUT) копируется на другой дескриптор с индексом не ниже 10 (это то, что делает F_DUPFD; он возвращает наименьший доступный дескриптор, начиная с заданного номера, после дублирования на этот дескриптор). Также посмотрите, как в строке 137 результат open("/dev/null") (дескриптор 3) копируется на дескриптор 1 (STDOUT). Наконец, в строке 147 старый STDOUT, сохраненный на дескрипторе 10, копируется обратно на дескриптор 1 (STDOUT). Чистый эффект заключается в изоляции изменения в STDOUT в строке 144 (что соответствует внутреннему exec >/dev/null).

14
27.01.2020, 19:49

Следуем

{ exec >/dev/null; } >/dev/null; echo "Hi"

шаг за шагом.

  1. Есть две команды:

    a. { exec >/dev/null; } >/dev/null, затем

    b. echo "Hi"

    Оболочка выполняет сначала команду (a), а затем команду (b).

  2. Выполнение { exec >/dev/null; } >/dev/null происходит следующим образом:

    a. Сначала оболочка выполняет перенаправление >/dev/null и не забывает отменить его при завершении команды.

    b. Затем оболочка выполняет { exec >/dev/null; }.

    c. Наконец, оболочка переключает стандартный вывод обратно на прежнее место. (Это тот же механизм, что и в ls -lR /usr/share/fonts >~/FontList.txt -- перенаправления выполняются только на время выполнения команды, к которой они относятся.)

  3. После выполнения первой команды shell выполняет echo "Hi". Стандартный вывод находится там, где он был до выполнения первой команды.

18
27.01.2020, 19:49

Разница между {exec> / dev / null;}> / dev / null; echo "Hi" и {exec> / dev / null;}; echo "Hi" означает, что двойное перенаправление выполняет dup2 (10, 1); перед закрытием fd 10, который является копией исходного stdout , перед запуском следующей команды ( echo ).

Это происходит потому, что внешнее перенаправление фактически перекрывает внутреннее перенаправление. Вот почему после завершения он копирует исходный stdout fd.

9
27.01.2020, 19:49

Теги

Похожие вопросы