Почему bash не создает подшивку для простых команд?

Правильное решение - восстановить файл из его последней резервной копии.

Копирование из /proc/PID/fd/ работает только в том случае, если у процесса в данный момент открыт файл. Он ничего не может сделать с файлом, который был открыт процессом в какой-то момент в прошлом, но больше не открыт. У программы нет необходимости держать открытым файл конфигурации: как только она прочитала свою конфигурацию, она закрывает файл. Таким образом вы ничего не восстановите. Файл, который вы пытаетесь восстановить, не имеет отношения к делу; это сетевой сокет, который прослушивает процесс, а вы не можете читать данные из такого сокета, не то чтобы это принесло вам какую-то пользу.

gcore 30495 как предложил Марк Плотник, сбросит образ памяти процесса в файл core.30495. Вы можете попытаться просмотреть этот образ памяти, но не надейтесь: велика вероятность, что процесс разобрал файл конфигурации и повторно использовал память, в которой хранился файл, для других целей. Возможно даже, что весь файл конфигурации никогда не хранился в памяти целиком, а только по частям, и каждая часть перезаписывала предыдущую.

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

На будущее, не забывайте делать резервные копии. И поместите ваши конфигурационные файлы под контроль версий (и делайте резервные копии репозитория).

5
06.02.2018, 19:29
2 ответа

Вывод pstreeвводит в заблуждение.

bash -c "sleep 10000 "

создает дочерний процесс bash. Но этот процесс не создает еще один дочерний процесс. Поскольку после запуска sleepделать больше нечего, оболочка делает прямой переход с execve()на sleepбез предварительного разветвления.

Поскольку это так быстро, вы просто видите результат после execveв pstree.

Но в

bash -c "sleep 10000; sleep 99999 "

случай, когда новый bash разветвляется дважды, по одному разу для каждой команды. Он также мог бы сделать execveдля последней команды вместо того, чтобы разветвляться первой. Я не знаю, почему это не так.

Это и случай с перенаправлением, вероятно, просто проблемы с обнаружением необходимости разветвления.

3
27.01.2020, 20:40

В первом примере оболочка с PID 100648 — это ваша интерактивная оболочка, а sleep— фактически процесс, заменивший процесс bash -c ''. Системный вызовexecve()порождает новую программу, которая сохраняет PID исходного процесса, вызвавшего ее, поэтому вы не видите здесь исходный bash -c ''. Простая причина, по которой простые команды заменяют процесс оболочки, заключается в том, что он экономит ресурсы, как объяснено в ответе Стефана .

Это также видно из простого теста в одном терминале:

$ echo $$
10250
$ bash -c 'sleep 60'

И в другом:

$ pstree -p 10250
bash(10250)───sleep(21031)

Что касается того, почему это происходит именно так, то это потому, что есть простая команда без конвейеров, иbashвыполняет прямое выполнение для простых команд .

Именно по этой причине bashраспознает, что у вас есть несколько операторов команд во втором примере, следовательно, для каждой sleepкоманды, которую вы имеете в "sleep 10000; sleep 99999 ". В первом случае execve()может просто заменить родительский процесс, и когда новый завершится -, проблем не возникнет. Но здесь оболочка не может выйти после завершения первой команды. Следовательно, будет fork и execve для sleep 10000, что вы видите в выводе pstree, а затем новый fork и execve для sleep 99999

.

Еще один тест, который вы можете выполнить, чтобы поверить, что простая команда в bash -c ''заменяет процесс оболочки, это:

$ bash -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid:  23946
/proc/23946/status:Pid: 23946

Обратите внимание, что такое поведение -специфично для bash. Для /bin/dashв дистрибутивах на основе Debian -(, а также очевидно в strace,тоже):

$ sh -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid:  24188
/proc/24187/status:Pid: 24187
1
27.01.2020, 20:40

Теги

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