Init = / path / to / program komutunun programa init olarak başlatılmamasını ne sağlayabilir?


13

Bir Linux sisteminde bir init betiğinde hata ayıklamaya çalışıyorum; Ben init dizisi manuel olarak çalıştırabilirsiniz böylece başlamadan init=/bin/shbaşlatmak için çekirdeği geçmek çalışıyorum .shinit

Bulduğum şey, çekirdeğin initzaten başlıyor olması . Önyükleme sırasında printk mesajlarından biri komut satırıdır ve satırın doğru ayarlandığını gösterir; buna ek olarak, çekirdek komut satırını kullanarak başka şeyleri de etkileyebilirim. Yolun var olduğundan emin olmak için kontrol ettim; öyle.

Bu bir meşgul kutusu sistemidir ve init, meşgul kutusuna bir sembolik bağlantıdır; Bu yüzden PID 1 olduğunda busybox garip büyü yapmadığından emin olmak için, aynı zamanda init olarak meşgul olmayan bir program çalıştırmayı denedim; bu da işe yaramadı. Ne yaparsam yapayım init çalıştırılıyor.

Bu davranışa ne sebep olabilir?


Meşgul kutusunu kullanan temel dağıtım nedir init? Sadece komut satırını görmezden gelebilirler ... initrd'i incelemek ve scriptlerin gerçekte ne yaptığını görmek isteyebilirsiniz .
Aaron D.Marasco

Bu herhangi bir dağıtım değil - bu benim kendi yapım; bu yüzden init betiklerinde hata ayıklamaya çalışıyorum.
Shawn J. Goff

Yanıtlar:


3

Linux çekirdek kaynağına baktığımda, eğer dosya / init varsa, çekirdek her zaman ramdisk önyüklemesi yaptığı varsayımıyla çalıştırmaya çalışacağını görüyorum. / İnit'in var olup olmadığını görmek için sisteminizi kontrol edin, eğer varsa, bu muhtemelen sizin probleminizdir.


Aslında, execute_commandönce çekirdek komut satırı init=parametresinden gelen kontrol eder . Yürütemezse, bir uyarı yazdırır ve initçeşitli konumlarda çalışmaya çalışır . Bu init/main.cişlevde init_post(). Çekirdek printk mesajlarına baktım ve çekirdeğimin çıktısında uyarı buldum, bu yüzden şimdi neden / bin / sh veya başlamaya çalıştığım başka bir şey başlayamadığını bulmalıyım.
Shawn J. Goff

Baktığım kod (v3.2.2 sanırım) ayarlanmadıysa set ramdisk_execute_command'ı kontrol etti ve daha sonra çalıştırmayı denedi, bu yüzden bu güncel olmamalısınız. Çok kötü, çünkü açıklayacak başka bir şey görmedim.
Kyle Jones


8

initrd maskaralık

İnitrd veya initramfs kullanıyorsanız aşağıdakileri unutmayın:

  • rdinit= yerine kullanılır init=

  • eğer rdinit=verilmez, teşebbüs varsayılan yollar şunlardır: /sbin/init, /etc/init, /bin/initve /bin/shfakat/init

    İnitrd kullanılmadığında, /initdenenen ilk yol, ardından diğerleri izlenir.

v4.15 RTFS: her şey https://github.com/torvalds/linux/blob/v4.15/init/main.c dosyasında bulunur.

İlk önce şunu öğreniyoruz:

  • execute_comand ne olursa olsun: init=
  • ramdisk_execute_command ne olursa olsun: rdinit=

görüldüğü gibi:

static int __init init_setup(char *str)
{
    unsigned int i;

    execute_command = str;
    /*
    * In case LILO is going to boot us with default command line,
    * it prepends "auto" before the whole cmdline which makes
    * the shell think it should execute a script with such name.
    * So we ignore all arguments entered _before_ init=... [MJ]
    */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("init=", init_setup);

static int __init rdinit_setup(char *str)
{
    unsigned int i;

    ramdisk_execute_command = str;
    /* See "auto" comment in init_setup */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("rdinit=", rdinit_setup);

Burada __setupkomut satırı parametrelerini ele almanın sihirli bir yolu var.

start_kernel, bir iş parçacığında rest_init"çağıran" çekirdek "giriş noktası", çağrılar kernel_init:

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

Sonra kernel_inityapar:

static int __ref kernel_init(void *unused)
{
    int ret;

    kernel_init_freeable();

    [...]

    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return 0;
        pr_err("Failed to execute %s (error %d)\n",
            ramdisk_execute_command, ret);
    }

    [...]

    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return 0;
        panic("Requested init %s failed (error %d).",
            execute_command, ret);
    }
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    panic("No working init found.  Try passing init= option to kernel. "
        "See Linux Documentation/admin-guide/init.rst for guidance.");
}

ve kernel_init_freeableyapar:

static noinline void __init kernel_init_freeable(void)
{

    [...]

    if (!ramdisk_execute_command)
        ramdisk_execute_command = "/init";

    if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
        ramdisk_execute_command = NULL;
        prepare_namespace();
    }

YAPILACAKLAR: anlayın sys_access.

Ayrıca ram girişleri ile ram olmayan girişler arasında daha fazla farklılık olduğunu unutmayın, örn. Konsol kullanımı: Katıştırılmış veya harici initramfs ile init yürütme farkı?



0

Linux çekirdeğinizi özelleştirebilir ve yeniden derleyebilirsiniz. 4.9 çekirdek için, init / main.c içindeki "kernel_init" işlevini düzenleyin ve önce aşağıdaki satırı çalıştırmayı deneyin:

try_to_run_init_process("/bin/sh")

Buna ek olarak, BootLoader tarafından geçirilen çekirdek parametreleri de olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.