Хорошо, проблема решена путем выполнения этих команд и перезагрузки:
sudo modprobe -r acer_wmi
sudo rfkill unblock all
echo "blacklist acer_wmi" | sudo tee /etc/modprobe.d/acer-wmi.conf
Чтобы не использовать под-оболочку или под-процесс, когда вывод составного списка {}
передается по трубопроводу >
, оболочка сохраняет дескриптор 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
).
Следуем
{ exec >/dev/null; } >/dev/null; echo "Hi"
шаг за шагом.
Есть две команды:
a. { exec >/dev/null; } >/dev/null
, затем
b. echo "Hi"
Оболочка выполняет сначала команду (a), а затем команду (b).
Выполнение { exec >/dev/null; } >/dev/null
происходит следующим образом:
a. Сначала оболочка выполняет перенаправление >/dev/null
и не забывает отменить его при завершении команды.
b. Затем оболочка выполняет { exec >/dev/null; }
.
c. Наконец, оболочка переключает стандартный вывод обратно на прежнее место. (Это тот же механизм, что и в ls -lR /usr/share/fonts >~/FontList.txt
-- перенаправления выполняются только на время выполнения команды, к которой они относятся.)
После выполнения первой команды shell выполняет echo "Hi"
. Стандартный вывод находится там, где он был до выполнения первой команды.
Разница между {exec> / dev / null;}> / dev / null; echo "Hi"
и {exec> / dev / null;}; echo "Hi"
означает, что двойное перенаправление выполняет dup2 (10, 1);
перед закрытием fd 10, который является копией исходного stdout
, перед запуском следующей команды ( echo
).
Это происходит потому, что внешнее перенаправление фактически перекрывает внутреннее перенаправление. Вот почему после завершения он копирует исходный stdout
fd.