Пока я не начал отвечать на этот вопрос, я не осознавал, что использование управляющего оператора &
для запуска задания в фоновом режиме запускает подоболочку. Подоболочки создаются, когда команды заключаются в круглые скобки или образуют часть конвейера (каждая команда в конвейере выполняется в своей собственной подоболочке).
В разделе Списки команд руководства Bash ( спасибо jimmij ) говорится:
Если команда завершается управляющим оператором '&', оболочка выполняет { {1}} команда асинхронно в подоболочке. Это называется выполнением команды в фоне . Оболочка не ждет, пока команда завершится , и статус возврата - 0 (истина).
Насколько я понимаю, когда вы запускаете sleep 10 и
shell fork s для создания нового дочернего процесса (его копии), а затем немедленно exec , чтобы заменить этот дочерний процесс кодом из внешней команды ( sleep
). Это похоже на то, что происходит, когда команда выполняется в обычном режиме (на переднем плане). См. Статью в Википедии Fork – exec для краткого обзора этого механизма.
Я не мог понять, почему Bash запускает фоновые команды в подоболочке, но это имеет смысл, если вы также хотите иметь возможность запускать встроенные команды оболочки, такие как exit
или echo
для работать в фоновом режиме (а не только внешними командами).
Когда встроенная оболочка запускается в фоновом режиме, форк
происходит (в результате получается подоболочка) без вызова exec
для замены себя внешней командой. Выполнение следующих команд показывает, что когда команда echo
заключена в фигурные скобки и выполняется в фоновом режиме (с помощью &
), подоболочка действительно создается:
$ { echo $BASH_SUBSHELL $BASHPID; }
0 21516
$ { echo $BASH_SUBSHELL $BASHPID; } &
[1] 22064
$ 1 22064
например, я заключил команду echo
в фигурные скобки, чтобы избежать расширения BASH_SUBSHELL
текущей оболочкой; фигурные скобки используются для группировки команд без использования подоболочки. Вторая версия команды (заканчивающаяся управляющим оператором &
) ясно демонстрирует, что завершение команды амперсандом привело к созданию подоболочки (с новым PID) для выполнения echo
встроенный. (Я, вероятно, здесь упрощаю поведение оболочки. См. Комментарий mikeserv.)
Я бы никогда не подумал запустить exit &
, и если бы я не прочитал ваш вопрос, я бы ожидал, что текущая оболочка для выхода. Теперь, когда вы знаете, что такие команды выполняются в подоболочке, ваше объяснение, что выходит именно из подоболочки, имеет смысл.
«Почему подоболочка, созданная оператором управления фоном (&), не отображается в pstree»
Как упоминалось выше, когда вы запускаете sleep 10 &
, Bash разветвляется для создания подоболочки, но поскольку sleep
- внешняя команда, она вызывает системный вызов exec ()
, который немедленно заменяет код Bash и данные в дочернем процессе на работающую копию sleep
программа. К тому времени, когда вы запустите pstree
, вызов exec
уже будет завершен, и теперь дочерний процесс будет иметь имя « sleep ».
Находясь вдали от своего компьютера, я попытался придумать способ поддерживать подоболочку в работе достаточно долго, чтобы подоболочка отображалась pstree
. Я решил, что мы можем запустить команду через time
builtin:
$ time sleep 11 &
[2] 4502
$ pstree -p 26793
bash(26793)─┬─bash(4502)───sleep(4503)
└─pstree(4504)
Здесь оболочка Bash (26793) разветвляется для создания подоболочки (4502) для выполнения команды в фоновом режиме. Эта подоболочка запускает собственную встроенную команду time
, которая, в свою очередь, выполняет ветвление (для создания нового процесса с PID 4503) и запускает внешнюю команду sleep
.
Используя именованные каналы , jimmij придумал хитрый способ поддерживать подоболочку, созданную для запуска exit
, достаточно долго, чтобы она отображалась pstree
:
$ mkfifo file
$ exit file
$ jobs
[2]- Done exit < file
Перенаправление stdin
из именованного канала является разумным, поскольку оно заставляет подоболочку блокироваться до тех пор, пока она не получит входные данные из именованного канала.Позже, перенаправление вывода echo
(без каких-либо аргументов) записывает символ новой строки в именованный канал, который разблокирует процесс подоболочки, который, в свою очередь, запускает встроенную команду exit
.
Аналогично для команды sleep
:
$ mkfifo named_pipe
$ sleep 11 < named_pipe &
[1] 6600
$ pstree -p 26793
bash(26793)─┬─bash(6600)
└─pstree(6603)
Здесь мы видим, что подоболочка, созданная для выполнения команды в фоновом режиме, имеет PID 6600
. Затем мы разблокируем процесс, записывая символ новой строки в конвейер:
$ echo > named_pipe
подоболочка, затем exec
s для выполнения команды sleep
.
$ pstree -p 26793
bash(26793)─┬─pstree(6607)
└─sleep(6600)
После вызова exec ()
мы видим, что дочерний процесс ( 6600
)теперь работает программа сна
.
Способ, которым вы разбили дисковое пространство на разделы, кажется произвольным и в равной степени неоптимальным, и я не совсем уверен, почему вы сделали это в первую очередь, но не будем об этом говорить.
Я заметил, что ваш корневой раздел
root@debian:/home/midhun# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda11 91G 11G 76G 12% /
имеет много свободного места, а /usr
полностью закончилось.
Вот как я подхожу к этой задаче -вам нужно будет загрузиться с live CD/USB flash, чтобы сделать следующее:
/usr
из/etc/fstab
umount /usr/local
(на всякий случай)cp -a --preserve=all /usr /usr-new
umount /usr
rmdir /usr
mv /usr-new /usr
В качестве альтернативы вы можете запустить sudo du -x /usr | sort -n | tail -30
и посмотреть, какие каталоги занимают больше всего места.
Затем используйте sudo dpkg-query -S /path
, чтобы узнать, к каким пакетам они принадлежат, и удалите их с помощью sudo apt remove packagename
.
Вы уже сделали это, смонтировав свободный диск/раздел (/dev/sda16 )в /usr/local
. Вы можете сделать то же самое с другими «большими» каталогами, но, пожалуйста, убедитесь, что вы понимаете разветвления, поскольку это усложняет работу и может оставить систему в затруднительном состоянии.
сначала запустите это, чтобы определить самые большие каталоги в вашей системе
sudo du -k / | sort -n|tail -222
затем rm
указать оскорбительные каталоги в /home
вы можете просто сфокусироваться напрямую, используя
sudo du -k /home | sort -n|tail -222
sudo du -k /usr | sort -n|tail -222
это покажет большие пакеты
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n
Если вы видите некоторые из них, которые вы недавно установили и/или знаете, что не используете, они являются кандидатами на удаление
Другой способ — просмотреть недавно установленные пакеты, выполнив
grep " install " /var/log/dpkg.log
, чтобы узнать, не являются ли какие-либо из них необязательными и могут быть удалены
Избегайте прямого удаления чего-либо в /usr, так как он содержит важные системные инструменты, удаление которых может привести к повреждению системы. Вместо этого определите необязательные пакеты, а затем используйте обычные команды для удаления этих пакетов-кандидатов.
sudo apt remove unused-big-package
sudo apt purge unused-big-package # this also removes its configs