Как выйти из chroot внутри скрипта perl?

#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:

Похоже, это может быть многообещающим:

Выход из тюрьмы Chroot с использованием PERL

Комментарии:

1. На этой странице рассказывается о выходе из chroot и извлечении из него оболочки, это повышение привилегий. Я пробовал это, но в моем случае это не сработает. Мне нужно размонтировать диск, на котором запущен скрипт, поэтому мне нужно, чтобы он был либо уничтожен, либо вне chroot. В любом случае спасибо.

Ответ №5:

Сохраните исходный корень как текущий рабочий каталог или как файловый дескриптор:

 chdir "/";
chroot "/mnt";
# Do something
chroot ".";
  

или

 open DIR, "<", "/";
chroot "/mnt";
# Do something
chdir DIR;
chroot ".";
close DIR;