#linux #perl #chroot
#linux #perl #chroot
Вопрос:
При написании скрипта perl, предназначенного для полной автоматизации настройки виртуальных машин (Xen pv), я столкнулся с небольшой, возможно, очень простой проблемой.
Используя функцию chroot в perl, я делаю свои дела в гостевой файловой системе, а затем мне нужно вернуться к своему первоначальному реальному корню. Как, черт возьми, я это делаю?
Пример скрипта:
`mount $disk_image $mount_point`;
chdir($mount_point);
chroot($mount_point);
#[Do my things...]
#<Exit chroot wanted here>
`umount $mount_point`;
#[Post install things...]
Я пробовал exit; но, очевидно, это завершает работу всего скрипта.
В поисках способа выхода из chroot я нашел несколько сценариев, целью которых является выход из уже настроенного chroot (повышение привилегий). Поскольку я использую chroot здесь, эти методы не применяются.
Пробовал некоторые сумасшедшие вещи, такие как:
opendir REAL_ROOT, "/";
chdir($mount_point);
chroot($mount_point);
chdir(*REAL_ROOT);
Но не получается.
ОБНОВИТЕ некоторые моменты, которые следует учитывать:
- Я не могу разделить скрипт на несколько файлов. (Глупые причины, но на самом деле я не могу)
- Часть, связанная с chrooted, включает в себя использование большого количества данных, собранных ранее скриптом (до chroot), что приводит к необходимости не запускать другой скрипт внутри chroot.
- Использование open, system или backticks не подходит, мне нужно запускать команды и на основе выходных данных (не кода выхода, фактического вывода) выполнять другие действия.
- Шаги после chroot зависят от того, что было сделано внутри chroot, поэтому мне нужно иметь все переменные, которые я определил или изменил, находясь внутри, снаружи.
- Форк возможен, но я не знаю хорошего способа корректно обрабатывать передачу информации от дочернего элемента и к нему.
Комментарии:
1. Я думаю, вам нужно разветвить часть с chrooted и дождаться ее выхода.
Ответ №1:
Процесс chrooted () не может «выкорчевать» себя путем выхода (который просто завершится).
Вы должны создать дочерний процесс, который будет chroot.
Что-то вроде следующего должно сработать:
if (fork())
{
# parent
wait;
}
else
{
# children
chroot("/path/to/somewhere/");
# do some Perl stuff inside the chroot...
exit;
}
# The parent can continue it's stuff after his chrooted children did some others stuff...
В нем по-прежнему отсутствуют некоторые мысли о проверке ошибок.
Комментарии:
1. Спасибо всем, кто упомянул, что это невозможно. И предоставление решения fork. Не так элегантно, как я ожидал, но сойдет. Спасибо и за пример.
Ответ №2:
Вы не можете отменить a chroot()
в процессе — в этом весь смысл системного вызова.
Вам нужен второй процесс (дочерний процесс) для выполнения работы в среде с chrooted. Разветвляйте, и пусть дочерний элемент проходит chroot
и выполняет свои действия и завершает работу, оставляя родительский элемент для очистки.
Ответ №3:
Попробуйте создать дочерний процесс, который выполняет chroot
, например, с system
или fork
в зависимости от ваших потребностей, и дождаться, пока дочерний процесс вернет основную программу, продолжается.
Комментарии:
1. Это первое, что я сделал. Но был слишком ограничен. Мне нужно запускать команды и получать их вывод. Выполнение
open(CHROOT, "chroot '$mount_point' /bin/bash |");
— это не чтение / запись, а только одно или другое.2. @Alexandre — Используется
IPC::Open3
для выполнения как чтения, так и записи во внешней команде.
Ответ №4:
Похоже, это может быть многообещающим:
Комментарии:
1. На этой странице рассказывается о выходе из chroot и извлечении из него оболочки, это повышение привилегий. Я пробовал это, но в моем случае это не сработает. Мне нужно размонтировать диск, на котором запущен скрипт, поэтому мне нужно, чтобы он был либо уничтожен, либо вне chroot. В любом случае спасибо.
Ответ №5:
Сохраните исходный корень как текущий рабочий каталог или как файловый дескриптор:
chdir "/";
chroot "/mnt";
# Do something
chroot ".";
или
open DIR, "<", "/";
chroot "/mnt";
# Do something
chdir DIR;
chroot ".";
close DIR;