© Anton Dolganin 2026
Многие думают, что командная строка (bash, zsh), в которую мы вводим команды — это какая-то глубоко встроенная, магическая часть операционной системы.
На самом деле, шелл — это лишь стартовая программа на вашем сервере. Когда вы логинитесь по SSH, система заглядывает в файл конфигурации пользователя и запускает то, что там указано. Если вместо /bin/bash там прописать путь к Python, вы попадете в интерпретатор Python. Пропишете /usr/bin/top — откроется диспетчер задач, а при выходе из него ваш SSH-сеанс сразу закроется.
Но как устроен сам шелл изнутри? Фундаментально — это просто бесконечный цикл. Вот как выглядит его минималистичный скелет на современном C.
Минимальный шелл (на базе паттерна из UNIX)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAXLINE 4096
int main(void) {
char buf[MAXLINE];
printf("%% ");
while (fgets(buf, MAXLINE, stdin) != NULL) {
size_t len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n') {
buf[len - 1] = '\0';
}
pid_t pid = fork();
if (pid < 0) {
perror("fork error");
exit(EXIT_FAILURE);
} else if (pid == 0) { /* child process */
execlp(buf, buf, (char *)NULL);
/* if execlp returns control, then an error occurred. */
fprintf(stderr, "couldn't execute: %s\n", buf);
exit(127);
}
/* parent process */
int status;
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid error");
exit(EXIT_FAILURE);
}
printf("%% ");
}
exit(EXIT_SUCCESS);
}
Как это работает под капотом
Вся суть классического UNIX-шелла сводится к паттерну fork-exec-wait, который можно описать пятью простыми шагами:
%.В чем заключается «магия форка»?
После вызова функции fork() операционная система клонирует процесс. Оба процесса продолжают работу буквально с одной и той же строчки кода (возврата из функции fork). Отличаются они только одним: в дочернем процессе функция возвращает 0, а родитель получает ID свежесозданного клона. Это значение работает как развилка, заставляя процессы пойти по разным веткам if-else.
Важная оговорка:
Этот код намеренно «деревянный» и служит только для учебных целей. Он не умеет обрабатывать параметры (команда вроде ls -l выдаст ошибку, так как система будет искать один файл с пробелом в названии), не поддерживает встроенные команды вроде cd или exit, а также пайпы. Настоящий шелл перед вызовом exec проводит огромную работу по разбиению вашей строки на токены и настройке файловых дескрипторов. Тем не менее, абсолютно любой терминал базируется именно на этом элегантном механизме.
© Anton Dolganin 2026