init = / path / to / program을 커널에 전달하여 프로그램을 init로 시작하지 않는 것은 무엇입니까?


13

Linux 시스템에서 init 스크립트를 디버깅하려고합니다. init=/bin/sh커널을 시작 sh하지 않고 시작 init하도록 초기화 하려고 하므로 초기화 시퀀스를 수동으로 실행할 수 있습니다.

내가 찾은 것은 init어쨌든 커널이 시작되고 있다는 것입니다. 부팅하는 동안 printk 메시지 중 하나가 명령 줄이며, 해당 줄이 올바르게 설정되어 있음을 나타냅니다. 또한 커널 명령 줄을 사용하여 다른 것에 영향을 줄 수 있습니다. 경로가 존재하는지 확인했습니다. 그렇습니다.

이것은 busybox 시스템이며 init는 busybox에 대한 심볼릭 링크입니다. 따라서 busybox가 PID가 1 일 때 이상한 마술을하지 않도록하기 위해 비 busybox 프로그램을 init로 실행 해 보았습니다. 그것도 작동하지 않았다. 내가 무엇을하든 초기화가 실행되는 것 같습니다.

이 문제의 원인은 무엇입니까?


busybox를 사용하는 기본 배포판은 무엇입니까 init? 그들은 단순히 명령 줄을 무시하고있을 수 있습니다 ... initrd검사 하고 스크립트가 실제로 무엇을하고 있는지 확인할 수 있습니다.
Aaron D. Marasco

그것은 배포판이 아닙니다-그것은 내 자신의 빌드입니다. 그래서 init 스크립트를 디버깅하려고합니다.
숀 J. 고프

답변:


3

리눅스 커널 소스를 살펴보면, / init 파일이 존재하면 커널은 항상 램 디스크 부팅을하고 있다는 가정하에 커널을 실행하려고 시도합니다. 시스템에 / init가 있는지 확인하십시오. 존재하는 경우 문제 일 수 있습니다.


실제로 execute_command커널 명령 행 init=매개 변수 에서 오는 것을 먼저 확인합니다 . 실행할 수 없으면 경고를 인쇄하고 init다양한 위치에서 실행 을 시도합니다 . 이것은 init/main.c기능에 init_post()있습니다. 커널 printk 메시지를 살펴보고 커널 출력에서 ​​경고를 찾았으므로 이제 왜 / bin / sh를 시작할 수 없는지 또는 시작하려는 다른 것을 알아 내야합니다.
Shawn J. Goff

내가 본 코드 (v3.2.2)는 set ramdisk_execute_command가 설정되어 있지 않은지 확인한 다음 실행하려고 했으므로 현재 코드가 아니어야합니다. 내가 설명 할 다른 것을 보지 못했기 때문에 너무 나쁩니다.
Kyle Jones

당신은 사용해야합니다 rdinit: 분명히 램 디스크에서 부팅 할 때 unix.stackexchange.com/a/430614/32558
치로 틸리가新疆改造中心法轮功六四事件

8

initrd shenanigans

initrd 또는 initramfs를 사용하는 경우 다음을 명심하십시오.

  • rdinit= 대신에 사용 init=

  • 경우에 rdinit=주어지지 않는, 시도 기본 경로는 다음과 같습니다 /sbin/init, /etc/init, /bin/init/bin/sh는 아니지만/init

    initrd를 사용하지 않을 때는 /init첫 번째 경로를 시도한 후 다른 경로를 시도합니다.

v4.15 RTFS : 모든 것이 https://github.com/torvalds/linux/blob/v4.15/init/main.c 파일에 포함되어 있습니다.

먼저 우리는 그것을 배웁니다.

  • execute_comand 전달 된 것입니다 : init=
  • ramdisk_execute_command 전달 된 것입니다 : rdinit=

에서 볼 수 있듯이 :

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);

여기서 __setup명령 줄 매개 변수를 처리하는 마법의 방법입니다.

start_kernel커널 "entry point"는을 호출 하고 스레드에서 rest_init"호출" kernel_init합니다.

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

그런 다음 kernel_init을 수행합니다

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.");
}

그리고 kernel_init_freeable않습니다 :

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();
    }

TODO : 이해하십시오 sys_access.

또한 램 초기화와 비램 초기화 사이에는 추가적인 차이점이 있습니다. 예 : 콘솔 처리 : 내장형 대 외부 initramfs를 사용한 초기화 실행의 차이?



0

Linux 커널을 사용자 정의하고 다시 컴파일 할 수 있습니다. 4.9 커널의 경우 init / main.c에서 "kernel_init"함수를 편집하고 다음 행을 먼저 실행하십시오.

try_to_run_init_process("/bin/sh")

또한 BootLoader가 전달한 커널 매개 변수로 인해 발생할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.