bash — это обычная программка, такая же, как и любая другая, поэтому вы можете запускать ее по имени в командной строке.По умолчанию
bash запускает интерактивную оболочку для ввода и выполнения команд. Кроме того, можно передать команду в
bash в виде строки с помощью параметра -c. Тогда bash запустит эту строку как команду, а после выполнения завершит работу:$ bash -c "ls -l"
-rw-r--r-- 1 smith smith 325 Jul 3 17:44 animals.txt
🤔 Почему это бывает полезно?
Потому что новый процесс будет дочерним со своим собственным окружением, включая текущий каталог, переменные и их значения.
Любые изменения в дочерней оболочке не повлияют на текущую:
$ pwd
/home/smith
$ touch /tmp/badfile
$ bash -c "cd /tmp && rm badfile"
$ pwd
/home/smith
Пример выше запускает дополнительную оболочку только для того, чтобы сменить каталог на "tmp" и удалить файл, а затем завершает работу.
‼️ Однако наиболее показательно и полезно использование
bash -c вместе с sudo и перенаправлением ввода/вывода. Тогда-то эта фича и является ключом к успеху.Предположим, вы хотите создать файл журнала в системном каталоге "/var/log", недоступном для записи обычным пользователям.
Вы добавляете
sudo, чтобы получить привилегии и создать файл журнала, но команда почему-то не исполняется:$ sudo echo "New log file" > /var/log/custom.log
bash: /var/log/custom.log: Permission denied
🤔 Минуточку, но ведь команда sudo должна дать разрешение на создание любого файла в любом месте! Как что-то может пойти не так?
Почему
sudo даже не запрашивает пароль? Ответ: потому что sudo вообще не запускалась.Вы применили
sudo к команде echo, но не к перенаправлению вывода, которое запустилось первым и провалилось.✏️ Опишем процесс пошагово:
1) Вы нажали клавишу Enter.
2) Оболочка начала вычислять всю команду, включая перенаправление.
3) Оболочка попыталась создать файл custom.log в защищенном каталоге "/var/log".
У нас не было разрешения на запись в "/var/log", поэтому оболочка сообщила, что в доступе отказано (Permission denied).
Чтобы решить эту проблему, нужно сообщить оболочке: «Выполни всю команду, включая перенаправление вывода, от имени суперпользователя».
Это именно та ситуация, которую так хорошо решает
bash -c. Создайте команду, которую вы хотите запустить, в виде строки и передайте ее в качестве аргумента для
sudo bash -c:$ sudo bash -c 'echo "New log file" > /var/log/custom.log'
[sudo] password for smith: xxxxxxxx
$ cat /var/log/custom.log
New log file
На этот раз мы запустили от имени суперпользователя
bash, а не просто echo.По итогу,
bash выполнит всю строку как команду. Перенаправление проходит успешно. Помните о
bash -c, когда sudo сочетается с перенаправлением.