Как работает встроенная в Bash структура управления/перенаправление команд

В каталоге /etc/skelнаходится шаблон домашнего каталога. Вы можете попробовать восстановить права доступа к основным папкам в соответствии с папками в /etc/skel.

В будущем используйте rsync/cp/scp с -переключателем p для сохранения разрешений.

1
14.08.2017, 01:46
2 ответа

Обычно оболочки UNIX просто открывают необходимые файлы с помощью open, затем forkсами, затем dup2ранее полученные fd в stdin/stdout/stderr (0/1/2 ), чтобы они Обрабатываются соответственно программой они execveпозже. Для повышения производительности со встроенными командами может быть по-другому (, так как forkи execveдовольно дороги ), но семантика та же.

Если вы имеете в виду правила синтаксического анализа командной строки, то они описаны в POSIX. Они не различают встроенные и внешние программы.

3
27.01.2020, 23:24

Перенаправление дескриптора файла d0 в файл или из файла включает следующие шаги:

  1. Откройте файл. Файл открывается на некотором файловом дескрипторе d1 .
  2. Дублировать дескриптор d0 в текущий -неиспользуемый файловый дескриптор d2 , который больше, чем d0 . Это можно сделать с помощью команды F_DUPFDсистемного вызова fcntl. Если d0 не открыто, ничего не делайте на этом шаге.
  3. Дублировать от d1 до d0 . Это можно сделать с помощью F_DUPFDили с помощью dup2.
  4. Закрыть d1 .

Причина, по которой необходимо дублирование в случайном порядке, заключается в том, что приложения не могут выбирать файловый дескриптор при открытии файла. Шаги 2–4 можно пропустить, если d1 = d0 , но оболочка не может этого гарантировать.

Когда перенаправление применяется к внешней команде, оно выполняется в дочернем процессе после того, как дочерний процесс был создан с помощью fork, но до выполнения внешней команды с помощью execve. Когда перенаправление применяется к внутренней команде оболочки (, например. вызов функции, цикл и т. д. ), эти шаги должны выполняться в исходном процессе¹, и оболочке необходимо восстановить исходное состояние файлового дескриптора после завершения перенаправленной команды путем дублирования d2 вернуться к d0 и закрыть d2(или просто закрыть d0 , если он изначально не был открыт ).

Канал включает в себя аналогичные шаги, но немного сложнее, потому что создание канала создает два файловых дескриптора (конец чтения и конец записи )и есть два подпроцесса.

  1. Создайте трубу с помощьюpipe. Системный вызов pipeвозвращает пару файловых дескрипторов {r , w }.

  2. В левой -стороне трубы:

    1. Закрыть r .
    2. Перетасуйте дублирование, чтобы переместить w в 1.
  3. В правой -стороне трубы:

    1. Закрыть w .
    2. Перетасуйте дублирование, чтобы переместить r в 0.
  4. В оболочках, которые выполняют обе стороны канала в подпроцессах, родительский процесс закрывает r и w , затем ожидает завершения двух сторон канала.

    В оболочках, которые выполняют правую -сторону канала в родительском процессе, оболочка ожидает завершения левой -стороны, затем закрывает 0 и восстанавливает исходный дескриптор файла в 0.

Вы можете посмотреть, что делают оболочки, прочитав их исходный код или проследив за их работой с помощью отладчика. Например, в Linux посмотрите системные вызовы в действии с помощью

strace sh -c '…'

¹ Древние оболочки (до POSIX )выполняли перенаправленные сложные команды в подпроцессе, поэтому они не требовали восстановления перенаправления.

1
27.01.2020, 23:24

Теги

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