Как я могу проверить файловую систему контейнера-докера, которая не может быть запущена?

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

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

Что делает ваш скрипт:

  • читает строку кода
  • интерпретирует код, делая много дополнительных операций, чтобы фактически разобрать ваш ввод и понять, что делать
  • для каждой итерации цикла while (что, вероятно, недешево в интерпретируемом языке):
    • вызов внешней команды date и сохранение ее вывода (только в оригинальной версии - в пересмотренной версии вы выигрываете в 10 раз, не делая этого)
    • проверка выполнения условия завершения цикла
    • открытие файла в режиме append
    • разбор команды echo, распознать ее (с помощью некоторого кода сопоставления с образцом) как встроенный модуль оболочки, вызвать расширение параметров и все остальное на аргументе "GNU", и, наконец, записать строку в открытый файл
    • закрыть файл снова
    • повторить процесс

Дорогие части: вся интерпретация чрезвычайно дорога (bash выполняет огромное количество предварительной обработки всех входных данных - ваша строка потенциально может содержать подстановку переменных, подстановку процесса, расширение скобок, символы экранирования и многое другое), каждый вызов встроенного модуля, вероятно, является оператором switch с перенаправлением на функцию, которая работает со встроенным модулем, и, что очень важно, вы открываете и закрываете файл для каждой строки вывода. Вы можете поместить >> file вне цикла while, чтобы сделать это намного быстрее, но вы все еще находитесь в интерпретируемом языке. Вам очень повезло, что echo является встроенной командой оболочки, а не внешней командой - иначе ваш цикл создавал бы новый процесс (fork & exec) на каждой итерации. Что привело бы к остановке процесса - вы видели, насколько это дорого, когда в цикле была команда date.

2
30.11.2018, 18:44
1 ответ

Один из способов сделать это — создать новую фиксацию неисправного контейнера, а затем вызвать его с новой точкой входа.

Пример

Получить идентификатор контейнера

$ docker ps -a | grep prisma:1.21 | awk '{print $1}'
96b3a1ed8ae2

Создайте новую фиксацию для этого идентификатора контейнера

$ docker commit 29e98275723a tmpprisma
sha256:a83e0ee158d57f262230df752197a1f1e823660c42a9250e3c1ce803b41746c5

Введите образ контейнера с новой точкой входа

$ docker run -ti --entrypoint /bin/bash tmpprisma
bash-4.4#

Теперь можно проверить скрипт, который используется внутри контейнера

bash-4.4# ls -l app/bin/prisma-local
-rwxr--r--    1 root     root         16474 Apr 30  2018 app/bin/prisma-local
bash-4.4#

Ссылки

4
27.01.2020, 22:02

Теги

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