diff --git a/src/pages/linux/index.md b/src/pages/linux/index.md index c18fd6e..4f2e01e 100644 --- a/src/pages/linux/index.md +++ b/src/pages/linux/index.md @@ -23,12 +23,23 @@ Linux — семейство Unix-like operating systems на базе Linux ker **Полный ответ** -Linux — семейство Unix-like operating systems на базе Linux kernel. Для frontend-разработчика он важен потому, что -большая часть CI, Docker images, production servers и cloud-инфраструктуры работает именно в Linux-окружении. +Linux — это kernel и экосистема операционных систем вокруг него. Готовые дистрибутивы, например Ubuntu, Debian или +Fedora, добавляют userland utilities, package manager, init system и набор системных настроек. + +Frontend-разработчик обычно не администрирует Linux глубоко, но постоянно сталкивается с ним: + +- CI runners выполняют `npm ci`, tests и production build в Linux; +- Docker containers чаще всего основаны на Linux images; +- static files и SSR-приложения запускаются на Linux servers; +- shell scripts, permissions, paths и native dependencies могут вести себя иначе, чем на macOS или Windows. -Нужно уверенно ориентироваться в shell, filesystem, permissions, processes, network diagnostics и package managers. Это -помогает запускать проекты локально, читать CI logs, чинить окружение и понимать, почему команда работает в Docker или -на сервере иначе, чем на рабочем ноутбуке. +Например, import `./UserCard` может работать на case-insensitive filesystem macOS, но упасть в Linux CI, если файл +называется `user-card.ts`. Другой частый случай — script работает локально, но не запускается в CI из-за отсутствующего +execute permission. + +Практический минимум: понимать filesystem, shell, environment variables, processes, permissions, ports и package +management. Этого достаточно, чтобы диагностировать большую часть проблем окружения, не превращаясь в системного +администратора. @@ -46,9 +57,22 @@ kernels, системные утилиты и package managers. **Полный ответ** -Unix-like system следует идеям Unix: filesystem как дерево, процессы, текстовые streams, pipes, permissions и набор -маленьких утилит, которые можно комбинировать. Linux, macOS и BSD относятся к Unix-like системам, но используют разные -kernels, системные утилиты и package managers. +Unix-like называют систему, которая повторяет основные модели и пользовательские интерфейсы Unix, даже если не является +оригинальной Unix-системой. Обычно это означает: + +- единое дерево filesystem с root directory `/`; +- процессы с PID, environment и стандартными streams; +- модель owner/group/others и permissions; +- shell как основной интерфейс автоматизации; +- композицию маленьких программ через pipes; +- системные вызовы и API, похожие на POSIX. + +Linux, macOS и BSD поэтому ощущаются похожими: везде доступны `cd`, `ls`, `grep`, pipes и shell scripts. Но +совместимость не абсолютная. Linux часто использует GNU utilities, macOS — BSD utilities, а kernels, service managers и +package managers у систем разные. + +На интервью важно не говорить, что Linux и Unix — одно и то же. Linux является Unix-like системой, но не исходным Unix. +Также Unix-like не гарантирует, что любой shell script без изменений запустится во всех таких системах. @@ -65,11 +89,23 @@ Terminal — приложение или интерфейс, который по **Полный ответ** -Terminal — приложение или интерфейс, который показывает текстовый ввод/вывод. Shell — программа, которая интерпретирует -команды: `bash`, `zsh`, `fish`. +Terminal предоставляет пользовательский интерфейс: принимает нажатия клавиш, показывает текст и связывает ввод/вывод с +запущенным процессом. Современные Terminal, iTerm2, Windows Terminal и terminal в IDE являются terminal emulators. + +Shell — отдельная программа, которая работает внутри terminal. Она: -Например, в macOS Terminal или iTerm2 может запускать `zsh`, а в Linux terminal emulator может запускать `bash`. Разные -shells поддерживают похожий базовый синтаксис, но отличаются настройками, completion, history и расширениями. +1. читает командную строку; +2. раскрывает variables, globs и substitutions; +3. обрабатывает pipes и redirections; +4. находит executable через `PATH`; +5. запускает процессы и возвращает их exit code. + +Например, одно окно iTerm2 может запускать `zsh`, а другое — `bash`. Terminal останется тем же, но syntax, startup +files, completion и некоторые возможности shell будут отличаться. + +Shell может работать и без визуального terminal: CI запускает non-interactive shell для выполнения scripts. Поэтому +команда, которая работает в интерактивной сессии, иногда ломается в CI: там могут не загружаться `.zshrc`, aliases или +локальные environment variables. @@ -81,21 +117,32 @@ shells поддерживают похожий базовый синтаксис **Короткий ответ** -PATH — environment variable со списком directories, где shell ищет executable files. Когда выполняется node, shell -проходит по PATH слева направо и запускает первый найденный executable. +`PATH` — environment variable со списком directories, где shell ищет executable files. Когда выполняется `node`, shell +проходит по `PATH` слева направо и запускает первый найденный executable. **Полный ответ** -`PATH` — environment variable со списком directories, где shell ищет executable files. Когда выполняется `node`, shell -проходит по `PATH` слева направо и запускает первый найденный executable. +`PATH` содержит directories, разделенные двоеточием в Linux и macOS. Когда пользователь вводит `node`, shell не ищет +команду по всему диску, а последовательно проверяет directories из `PATH` и запускает первое совпадение. ```bash echo "$PATH" -which node -command -v npm +command -v node +type -a node ``` -Если команда не находится, нужно проверить установку пакета, путь к executable и конфигурацию shell startup files. +Порядок имеет значение. Если version manager добавил свою directory перед `/usr/local/bin`, будет запущена его версия +Node.js. Поэтому `node --version` у двух терминалов может отличаться после изменения startup files. + +Типичные проблемы: + +- package установлен, но его directory отсутствует в `PATH`; +- старая версия executable находится раньше новой; +- IDE и terminal получают разный `PATH`; +- script зависит от alias, которого нет в non-interactive shell. + +Добавлять current directory `.` в начало `PATH` небезопасно: команда может случайно запустить executable из +недоверенного проекта. Для локальных scripts лучше использовать явный путь `./script.sh`. @@ -107,23 +154,32 @@ command -v npm **Короткий ответ** -У процесса есть стандартные streams: +У процесса есть три стандартных потока: `stdin` для ввода, `stdout` для обычного результата и `stderr` для ошибок и +диагностики. **Полный ответ** -У процесса есть стандартные streams: +При запуске процесс обычно получает три открытых file descriptors: -- `stdin` — входные данные; -- `stdout` — обычный вывод; -- `stderr` — вывод ошибок и diagnostics. +- `0` — `stdin`, стандартный ввод; +- `1` — `stdout`, обычный результат; +- `2` — `stderr`, ошибки и диагностические сообщения. -Такой контракт позволяет связывать команды через pipes и отдельно обрабатывать результат и ошибки. +Благодаря общему контракту программа не обязана знать, откуда пришли данные и куда уйдет результат. Ввод может поступать +с клавиатуры, из файла или от другой программы, а вывод — отображаться в terminal, записываться в файл или передаваться +дальше через pipe. ```bash -cat package.json | grep scripts -npm run build > build.log 2> build-error.log +npm run build > build.log +npm run build 2> build-errors.log +npm run build > build.log 2>&1 ``` +Разделение `stdout` и `stderr` важно для автоматизации. Например, CLI может печатать JSON в `stdout`, а progress и +warnings — в `stderr`, чтобы другой процесс мог безопасно разобрать результат. + +Pipe `|` по умолчанию передает только `stdout`. Если нужно передать и ошибки, redirection задают явно. + @@ -134,19 +190,34 @@ npm run build > build.log 2> build-error.log **Короткий ответ** -Pipe | передает stdout одной команды в stdin следующей. Redirection записывает или читает stream из файла. +Pipe `|` передает `stdout` одной команды в `stdin` следующей. Redirection перенаправляет стандартные потоки в файл, из +файла или в другой file descriptor. **Полный ответ** -Pipe `|` передает `stdout` одной команды в `stdin` следующей. Redirection записывает или читает stream из файла. +Shell создает процессы и связывает их file descriptors до запуска команд. В pipeline команды обычно работают +одновременно: первая пишет данные, а следующая читает их по мере поступления. ```bash ps aux | grep node -ls -la > files.txt -npm test >> test.log +cat package.json | jq '.scripts' +``` + +Основные redirections: + +```bash +command > output.log # перезаписать stdout +command >> output.log # дописать stdout +command 2> errors.log # записать stderr +command > all.log 2>&1 # объединить stdout и stderr +command < input.txt # передать файл в stdin ``` -Это основа Unix-подхода: каждая утилита делает небольшую работу, а shell связывает их в workflow. +Не всегда нужен `cat`: вместо `cat file | grep text` можно написать `grep text file`. Но pipeline полезен, когда данные +действительно проходят через несколько независимых преобразований. + +В scripts важно учитывать exit codes pipeline. Без настройки shell итоговым обычно считается exit code последней +команды. В Bash `set -o pipefail` позволяет считать pipeline неуспешным, если упала любая его часть. @@ -160,11 +231,13 @@ npm test >> test.log **Короткий ответ** -pwd показывает current working directory. ls выводит содержимое directory. cd меняет current directory. +`pwd` показывает current working directory. `ls` выводит содержимое directory. `cd` меняет current directory текущего +shell. **Полный ответ** -`pwd` показывает current working directory. `ls` выводит содержимое directory. `cd` меняет current directory. +Каждый процесс имеет current working directory. Relative paths вычисляются относительно нее, поэтому перед запуском +script полезно понимать, где именно находится shell. ```bash pwd @@ -175,7 +248,14 @@ cd .. cd - ``` -`ls -la` часто используют, чтобы увидеть hidden files, permissions, owner, group, size и дату изменения. +`ls -la` показывает hidden files, permissions, owner, group, size и timestamps. `cd -` возвращает в предыдущую +directory, а `cd` без аргументов обычно переходит в home directory. + +Важно: `cd` изменяет directory только текущего shell. Отдельная программа не может изменить directory родительского +shell после завершения, поэтому `cd` обычно является built-in командой shell, а не внешним executable. + +В scripts надежнее вычислять paths явно, особенно если script могут запускать из разных directories. Частая ошибка — +предполагать, что current working directory всегда совпадает с directory самого script. @@ -187,28 +267,39 @@ cd - **Короткий ответ** -Базовые команды для работы с файлами и directories: +`mkdir` создает directory, `touch` создает пустой файл или обновляет timestamp, `cp` копирует, `mv` перемещает или +переименовывает, а `rm` удаляет files и directories. **Полный ответ** -Базовые команды для работы с файлами и directories: - -- `mkdir` создает directory; -- `touch` создает пустой файл или обновляет timestamp; -- `cp` копирует файл или directory; -- `mv` перемещает или переименовывает; -- `rm` удаляет файл. +Базовые операции выглядят так: ```bash mkdir -p src/pages/linux touch notes.md cp source.txt copy.txt +cp -R assets assets-backup mv old-name.txt new-name.txt rm unused.txt +rm -R generated +``` + +Полезные детали: + +- `mkdir -p` создает всю недостающую цепочку directories; +- `cp -R` нужен для directory; +- `mv` внутри одного filesystem обычно является быстрым rename, а между filesystems может потребовать копирования; +- `rm` удаляет сразу и обычно не использует корзину; +- `rm -R` рекурсивно удаляет directory, поэтому ошибка в path особенно опасна. + +В automated scripts стоит использовать защитные проверки и quoted variables: + +```bash +test -n "$BUILD_DIR" && rm -rf -- "$BUILD_DIR" ``` -`rm -r` удаляет directory рекурсивно. Команду нужно использовать внимательно, потому что обычный `rm` не отправляет файл -в корзину. +`touch` не гарантирует создание parent directory и не является полноценным редактором файла. Его часто используют для +создания marker files или обновления modification time. @@ -220,25 +311,30 @@ rm unused.txt **Короткий ответ** -Эти команды читают файлы: +`cat` печатает файл целиком, `less` открывает его постранично, `head` показывает начало, а `tail` — конец файла. **Полный ответ** -Эти команды читают файлы: - -- `cat` печатает файл целиком; -- `less` открывает файл постранично; -- `head` показывает начало; -- `tail` показывает конец. +Команду выбирают по размеру файла и задаче: ```bash cat package.json less README.md -head -20 src/pages/index.astro +head -n 20 server.log +tail -n 100 server.log tail -f server.log ``` -`tail -f` полезен для live logs: он продолжает показывать новые строки, которые дописываются в файл. +`cat` удобен для небольших text files или объединения нескольких файлов. Для большого log он может заполнить terminal +тысячами строк, поэтому лучше использовать `less`. + +`less` не загружает весь файл в интерфейс сразу, поддерживает поиск через `/text` и выход по `q`. `head` и `tail` +полезны в scripts, когда нужны только первые или последние строки. + +`tail -f` продолжает читать файл по мере добавления строк. Для log rotation иногда удобнее `tail -F`, который пытается +переоткрыть файл после его замены. + +Эти utilities рассчитаны прежде всего на text data. Вывод binary file через `cat` может испортить отображение terminal. @@ -250,21 +346,37 @@ tail -f server.log **Короткий ответ** -find ищет файлы по имени, типу, времени изменения и другим признакам. grep ищет текст по содержимому. rg или ripgrep — -быстрый современный аналог grep, который по умолчанию уважает .gitignore. +`find` ищет filesystem objects по имени, типу и metadata. `grep` ищет строки по содержимому. `rg` или ripgrep — быстрый +инструмент поиска по проекту, который по умолчанию учитывает `.gitignore`. **Полный ответ** -`find` ищет файлы по имени, типу, времени изменения и другим признакам. `grep` ищет текст по содержимому. `rg` или -ripgrep — быстрый современный аналог `grep`, который по умолчанию уважает `.gitignore`. +`find` обходит filesystem tree и фильтрует entries: + +```bash +find src -type f -name "index.md" +find . -type f -mtime -1 +``` + +`grep` ищет текст в переданных files или input stream: ```bash -find src -name "index.md" grep -R "Docker" src/pages +grep -n "error" server.log +``` + +`rg` оптимизирован для source repositories: + +```bash rg "kind: questions" src +rg --files | rg "index\.md$" ``` -Для больших frontend-репозиториев `rg` обычно удобнее и быстрее, чем рекурсивный `grep`. +Ripgrep обычно быстрее рекурсивного `grep`, пропускает ignored и hidden files, но это поведение можно изменить flags. +`find` лучше подходит, когда условие связано не с текстом, а с типом, размером, временем или permissions файла. + +Для scripts полезны exit codes: `0` означает, что совпадение найдено, `1` — совпадений нет, а больше `1` — ошибка. +Отсутствие совпадений не всегда должно считаться падением бизнес-сценария. @@ -276,16 +388,34 @@ rg "kind: questions" src **Короткий ответ** -Absolute path начинается от root directory, например /Users/name/project или /var/log/nginx/access.log. Relative path -считается от current working directory, например src/pages или ../README.md. +Absolute path начинается от root directory, например `/home/user/project`. Relative path вычисляется от current working +directory, например `src/pages` или `../README.md`. **Полный ответ** -Absolute path начинается от root directory, например `/Users/name/project` или `/var/log/nginx/access.log`. Relative -path считается от current working directory, например `src/pages` или `../README.md`. +Absolute path однозначно указывает location внутри текущего filesystem namespace: + +```text +/home/user/project/package.json +/var/log/nginx/access.log +``` + +Relative path зависит от current working directory: + +```text +src/pages +../README.md +./scripts/build.sh +``` + +Из-за этого один и тот же relative path может указывать на разные files в зависимости от места запуска команды. Это +частая причина расхождений между local environment, IDE и CI. -В scripts и CI лучше явно понимать, откуда выполняется команда. Ошибки с relative paths часто появляются, когда локально -команду запускают из одной directory, а в CI из другой. +Absolute paths удобны внутри конкретной машины, но плохо переносятся между пользователями и runners. В project scripts +обычно лучше строить path от repository root или directory самого script. + +Symlinks добавляют еще один нюанс: текстовый path и физический location могут отличаться. `pwd -P` показывает physical +path без symlinks, а обычный `pwd` может сохранять logical path пользователя. @@ -297,21 +427,34 @@ path считается от current working directory, например `src/pa **Короткий ответ** -. означает current directory. .. означает parent directory. обычно раскрывается в home directory текущего пользователя. +`.` означает current directory, `..` — parent directory, а `~` обычно раскрывается shell в home directory текущего +пользователя. **Полный ответ** -`.` означает current directory. `..` означает parent directory. `~` обычно раскрывается в home directory текущего -пользователя. +Эти обозначения используются при построении paths: ```bash -ls . +./scripts/build.sh cd .. -cd ~ +cd ~/projects ``` -В shell scripts важно помнить, что `~` раскрывается shell, а не любой программой. В quoted strings и config files это -может работать иначе. +`.` и `..` являются directory entries filesystem. `~` — не часть filesystem path сама по себе, а shell expansion. Shell +заменяет ее на значение home directory до запуска команды. + +Поэтому поведение зависит от контекста: + +```bash +echo ~ +echo "~" +``` + +В первом случае shell раскроет home directory, во втором quoted string останется `~`. Config parser или API также не +обязаны понимать tilde, если они не используют shell expansion. + +`.` в начале команды важно еще и потому, что current directory обычно отсутствует в `PATH`: `script.sh` может не +найтись, а `./script.sh` явно указывает нужный executable. @@ -325,18 +468,36 @@ cd ~ **Короткий ответ** -У файла есть owner, group и permissions для трех наборов пользователей: owner, group, others. Базовые права: +У filesystem object есть owner, group и permissions для трех категорий: owner, group и others. Базовые права — `r` +(read), `w` (write) и `x` (execute). **Полный ответ** -У файла есть owner, group и permissions для трех наборов пользователей: owner, group, others. Базовые права: +Вывод `ls -l` может выглядеть так: + +```text +-rwxr-xr-- 1 maxim developers 1200 Jul 28 build.sh +``` + +Первый символ обозначает тип объекта, следующие девять — права owner, group и others. -- `r` — read; -- `w` — write; -- `x` — execute или возможность зайти в directory. +Для обычного файла: -В выводе `ls -l` строка `-rwxr-xr--` показывает тип объекта и права. Для directory execute permission означает право -проходить через directory и обращаться к объектам внутри. +- `r` позволяет читать содержимое; +- `w` позволяет изменять содержимое; +- `x` позволяет запускать файл как executable. + +Для directory смысл отличается: + +- `r` позволяет получить список имен; +- `w` позволяет создавать и удалять entries; +- `x` позволяет проходить через directory и обращаться к объектам внутри. + +Права проверяются вместе с owner/group процесса. Новые files получают permissions с учетом `umask`, поэтому requested +mode может быть дополнительно ограничен. + +Классические permissions не покрывают все случаи: существуют ACL, capabilities, SELinux и AppArmor. Но для frontend и CI +обычно достаточно уверенно читать `ls -l` и понимать разницу прав файла и directory. @@ -348,20 +509,34 @@ cd ~ **Короткий ответ** -chmod меняет permissions, chown меняет owner, chgrp меняет group. +`chmod` меняет permissions, `chown` меняет owner, а `chgrp` меняет group filesystem object. **Полный ответ** -`chmod` меняет permissions, `chown` меняет owner, `chgrp` меняет group. +`chmod` поддерживает symbolic и numeric notation: ```bash chmod +x ./scripts/build.sh +chmod u=rw,g=r,o= README.md chmod 644 README.md -chown user:group file.txt -chgrp developers file.txt +chmod 755 ./scripts/build.sh +``` + +В numeric notation `4` означает read, `2` — write, `1` — execute. Значения складываются отдельно для owner, group и +others. + +`chown` и `chgrp` меняют ownership: + +```bash +sudo chown maxim:developers file.txt +sudo chgrp developers file.txt ``` -Для frontend-разработчика самый частый кейс — добавить execute permission script-файлу через `chmod +x`. +Обычный пользователь обычно не может произвольно передать файл другому owner. Recursive flags нужно применять осторожно: +ошибка в target directory может изменить ownership большого участка filesystem. + +Для frontend-разработчика частый случай — сохранить executable bit у shell script в Git. Если локально выполнить +`chmod +x script.sh` и закоммитить изменение mode, script сможет запускаться в Linux CI. @@ -373,16 +548,30 @@ chgrp developers file.txt **Короткий ответ** -sudo запускает команду с повышенными правами, обычно от root. Это нужно для системных операций: установка системных -пакетов, изменение protected directories, управление services. +`sudo` запускает разрешенную команду с повышенными правами, обычно от `root`. Он нужен для системных операций, а не для +обычной работы внутри project directory. **Полный ответ** -`sudo` запускает команду с повышенными правами, обычно от root. Это нужно для системных операций: установка системных -пакетов, изменение protected directories, управление services. +`sudo` проверяет policy, а затем запускает конкретную команду от другого пользователя, чаще всего `root`. Это не то же +самое, что постоянно работать в root shell: повышенные права применяются к ограниченной операции и могут +журналироваться. -Не стоит использовать `sudo` для исправления проблем с обычными project files или `node_modules`: так легко получить -файлы, которыми владеет root, и сломать локальную разработку. +Типичные случаи: + +```bash +sudo apt install nginx +sudo systemctl restart nginx +sudo chown maxim:developers /srv/app +``` + +Использовать `sudo` нужно по принципу least privilege. Ошибочная команда от root может удалить системные files или +изменить permissions всего проекта. + +Не стоит лечить `EACCES` через `sudo npm install`: после этого часть `node_modules` или cache может принадлежать root, и +обычные команды начнут падать. Лучше исправить ownership, настроить version manager или использовать user-space prefix. + +На production доступ через `sudo` часто ограничивают списком разрешенных команд, а не предоставляют полный root access. @@ -396,23 +585,34 @@ sudo запускает команду с повышенными правами, **Короткий ответ** -ps показывает processes snapshot. top и htop показывают процессы в интерактивном режиме. kill отправляет signal -процессу. +`ps` показывает snapshot процессов, `top` и `htop` отображают их в реальном времени, а `kill` отправляет process signal. **Полный ответ** -`ps` показывает processes snapshot. `top` и `htop` показывают процессы в интерактивном режиме. `kill` отправляет signal -процессу. +`ps` удобен для фильтрации и scripts: ```bash +ps aux ps aux | grep node -top -kill 12345 -kill -9 12345 +pgrep -af node ``` -Обычный `kill` отправляет `SIGTERM` и дает процессу шанс завершиться корректно. `kill -9` отправляет `SIGKILL`, который -нельзя обработать, поэтому его лучше оставлять для зависших процессов. +`top` и `htop` помогают видеть CPU, memory, load и наиболее тяжелые процессы. `htop` обычно удобнее интерактивно, но +может быть не установлен на сервере. + +`kill` не обязательно "убивает" процесс: команда отправляет signal по PID. + +```bash +kill 12345 # обычно SIGTERM +kill -INT 12345 # аналог прерывания +kill -9 12345 # SIGKILL +``` + +`SIGTERM` дает приложению возможность закрыть connections и записать данные. `SIGKILL` обрабатывается kernel немедленно, +поэтому cleanup выполнить нельзя. Его используют только когда корректное завершение не работает. + +PID может быть переиспользован после завершения процесса, поэтому перед `kill` нужно убедиться, что выбран нужный +process. @@ -424,19 +624,27 @@ kill -9 12345 **Короткий ответ** -На Linux часто используют ss, lsof или fuser. На macOS обычно доступен lsof. +На Linux используют `ss`, `lsof` или `fuser`, а на macOS чаще всего `lsof`. Они показывают listening socket и PID +процесса. **Полный ответ** -На Linux часто используют `ss`, `lsof` или `fuser`. На macOS обычно доступен `lsof`. +Примеры диагностики: ```bash ss -ltnp | grep :3000 -lsof -i :3000 +lsof -nP -iTCP:3000 -sTCP:LISTEN +fuser 3000/tcp ``` -После этого можно остановить процесс по PID. Важно убедиться, что это действительно ненужный dev server, а не системный -service. +Важно отличать listening socket от обычного исходящего connection. Для ошибки `EADDRINUSE` обычно нужен процесс со +статусом `LISTEN`. + +Socket привязан не только к port, но и к address. Процесс, слушающий `127.0.0.1:3000`, доступен только локально, а +`0.0.0.0:3000` принимает connections на всех IPv4 interfaces. + +После нахождения PID можно проверить команду и owner процесса, затем корректно остановить его через `SIGTERM`. Не +следует автоматически применять `kill -9`: занятый port может принадлежать database, proxy или другому нужному service. @@ -448,21 +656,30 @@ service. **Короткий ответ** -df показывает свободное место на mounted filesystems. du показывает размер files/directories. free показывает -использование памяти на Linux. +`df` показывает занятое место на mounted filesystems, `du` считает размер files и directories, а `free` показывает +использование RAM и swap в Linux. **Полный ответ** -`df` показывает свободное место на mounted filesystems. `du` показывает размер files/directories. `free` показывает -использование памяти на Linux. +Основные команды: ```bash df -h du -sh node_modules +du -h --max-depth=1 . free -h ``` -На macOS команды могут иметь другие опции, а `free` обычно отсутствует. +`df` смотрит на filesystem в целом, а `du` суммирует доступные ему directory entries. Их значения могут различаться, +например когда большой файл уже удален, но процесс продолжает держать его открытым. + +`du` может быть медленным на directory с сотнями тысяч files, например `node_modules`. Также результат зависит от +permissions и поддержки sparse files. + +В `free` поле `available` обычно полезнее простого `free`: Linux использует незанятую RAM для filesystem cache и может +освободить ее при необходимости. Высокое значение `used` само по себе не означает memory leak. + +На macOS `free` обычно отсутствует, поэтому используют Activity Monitor, `vm_stat` или другие system tools. @@ -474,21 +691,33 @@ free -h **Короткий ответ** -uname показывает информацию о системе и kernel. whoami показывает текущего пользователя. env выводит environment +`uname` показывает информацию о kernel и platform, `whoami` — effective user текущего процесса, а `env` — environment variables. **Полный ответ** -`uname` показывает информацию о системе и kernel. `whoami` показывает текущего пользователя. `env` выводит environment -variables. - ```bash uname -a +uname -m whoami env +printenv PATH ``` -Эти команды помогают быстро понять, где выполняется script: локально, в Docker, в Linux CI runner или на macOS. +`uname -m` помогает определить architecture, например `x86_64` или `arm64`. Это важно при установке native binaries и +диагностике несовместимых Docker images. + +`whoami` показывает effective user, что полезно при проблемах permissions в CI или container. Процесс может быть запущен +не тем пользователем, которого разработчик ожидает. + +`env` выводит environment и умеет запускать команду с временно измененными variables: + +```bash +NODE_ENV=production npm run build +env -i PATH="$PATH" npm run test +``` + +Environment может содержать tokens и passwords, поэтому его нельзя бездумно печатать в public CI logs. @@ -502,22 +731,32 @@ env **Короткий ответ** -ping проверяет базовую сетевую доступность через ICMP. curl выполняет HTTP и другие network requests. wget часто -используют для скачивания файлов. +`ping` проверяет ICMP-доступность host, `curl` выполняет network requests и показывает response, а `wget` ориентирован +на скачивание files. **Полный ответ** -`ping` проверяет базовую сетевую доступность через ICMP. `curl` выполняет HTTP и другие network requests. `wget` часто -используют для скачивания файлов. +`ping` проверяет, доходят ли ICMP echo packets и какова примерная latency: ```bash ping example.com +``` + +Но успешный `ping` не гарантирует работу HTTP, а неуспешный не доказывает недоступность server: ICMP часто блокируют +firewall rules. + +`curl` позволяет проверять конкретный protocol и endpoint: + +```bash curl -I https://example.com -curl http://localhost:3000/health -wget https://example.com/file.tar.gz +curl -v http://localhost:3000/health +curl -H 'Accept: application/json' https://api.example.com/users ``` -Для frontend-разработчика `curl` особенно полезен при проверке API, redirects, headers, cookies и local dev servers. +С его помощью диагностируют DNS, TLS, redirects, headers, cookies, status codes и API payload. + +`wget` удобен для downloads, recursive fetching и продолжения прерванной загрузки. Для CI важно проверять integrity +скачанного artifact, а не выполнять неизвестный script напрямую через `curl | sh`. @@ -529,19 +768,28 @@ wget https://example.com/file.tar.gz **Короткий ответ** -ssh подключается к удаленной машине по secure shell. scp копирует файлы через SSH. +`ssh` создает защищенное соединение с удаленной машиной и запускает shell или command. `scp` копирует files через SSH. **Полный ответ** -`ssh` подключается к удаленной машине по secure shell. `scp` копирует файлы через SSH. +Базовое подключение: ```bash ssh user@example.com +ssh user@example.com 'systemctl status app' scp ./dist/app.tar.gz user@example.com:/tmp/app.tar.gz ``` -В современной инфраструктуре прямой доступ на production может быть ограничен, но понимание SSH полезно для debugging, -CI secrets, deploy keys и работы с private Git repositories. +SSH обычно использует key pair. Private key остается у клиента, а public key добавляется на server. При первом +подключении клиент проверяет host key и сохраняет его в `known_hosts`, чтобы снизить риск man-in-the-middle attack. + +Для автоматизации применяют deploy keys, SSH agent и ограниченные credentials. Private keys нельзя хранить в repository +или печатать в CI logs. + +`scp` подходит для простого копирования. Для синхронизации directories часто удобнее `rsync` поверх SSH, потому что он +передает только изменения и поддерживает дополнительные проверки. + +Прямой SSH-доступ к production может быть запрещен, но понимание protocol полезно для Git, CI и диагностики servers. @@ -553,19 +801,27 @@ CI secrets, deploy keys и работы с private Git repositories. **Короткий ответ** -ifconfig — старая команда из net-tools. В современных Linux-дистрибутивах чаще используют ip из iproute2. +`ifconfig` — legacy utility из `net-tools`. В современных Linux-дистрибутивах interfaces, addresses и routes обычно +настраивают через команду `ip` из `iproute2`. **Полный ответ** -`ifconfig` — старая команда из net-tools. В современных Linux-дистрибутивах чаще используют `ip` из iproute2. +Современные Linux-команды: ```bash ip addr +ip link ip route ``` -На macOS `ifconfig` все еще обычный инструмент. Поэтому network commands часто отличаются между Linux и macOS, хотя -общие Unix-принципы похожи. +`ip addr` показывает addresses interfaces, `ip link` — состояние network links, `ip route` — routing table. `ifconfig` +покрывает часть этих задач, но развивается значительно меньше и может быть не установлен. + +На macOS `ifconfig` остается стандартной командой, а Linux-вариант `ip` обычно отсутствует. Поэтому инструкции нужно +адаптировать под target OS. + +Важно разделять уровни диагностики: interface может быть поднят, но route отсутствовать; route может работать, но DNS +быть сломан; DNS может разрешить имя, но application port быть закрыт. Одна команда не проверяет всю цепочку. @@ -579,19 +835,28 @@ ip route **Короткий ответ** -Package manager зависит от дистрибутива: +Package manager зависит от дистрибутива: Debian/Ubuntu используют `apt`, Fedora/RHEL — `dnf`, Arch — `pacman`, openSUSE +— `zypper`. **Полный ответ** -Package manager зависит от дистрибутива: +System package manager устанавливает packages из repositories дистрибутива, разрешает dependencies, проверяет signatures +и ведет database установленных files. + +Основные семейства: -- Debian/Ubuntu используют `apt`; -- Fedora/RHEL используют `dnf` или `yum`; -- Arch Linux использует `pacman`; -- openSUSE использует `zypper`; -- Snap и Flatpak распространяют приложения в более изолированном формате. +- Debian/Ubuntu — `apt` и `dpkg`; +- Fedora/RHEL — `dnf` и `rpm`; +- Arch Linux — `pacman`; +- openSUSE — `zypper`; +- Alpine Linux — `apk`. -Frontend-разработчик чаще всего встречает `apt` в Docker images и CI. +Snap и Flatpak распространяют applications в более изолированном формате, но не заменяют system packages во всех +сценариях. + +System package manager не следует путать с `npm`, `pnpm` или `pip`: первые управляют компонентами OS, вторые — +dependencies конкретной language ecosystem. В Docker image выбор команды зависит от base distribution: инструкция с +`apt` не сработает в `alpine`, где используется `apk`. @@ -603,21 +868,37 @@ Frontend-разработчик чаще всего встречает `apt` в **Короткий ответ** -apt устанавливает, обновляет и удаляет packages в Debian/Ubuntu. +`apt` обновляет package metadata, устанавливает, обновляет и удаляет packages в Debian и Ubuntu. **Полный ответ** -`apt` устанавливает, обновляет и удаляет packages в Debian/Ubuntu. +Базовый workflow: ```bash sudo apt update sudo apt install git curl -sudo apt upgrade -sudo apt remove package-name apt search package-name +apt show package-name +sudo apt remove package-name +sudo apt upgrade +``` + +`apt update` не обновляет сами packages — он скачивает актуальные indexes repositories. После этого `apt install` +выбирает доступную version и устанавливает dependencies. + +Для воспроизводимости важно понимать, что без version pinning одна и та же команда в разное время может установить +разные versions. В production images часто фиксируют base image digest или package version там, где это оправдано. + +В Dockerfile обычно используют non-interactive `apt-get`, объединяют update и install в один layer и удаляют package +lists: + +```dockerfile +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl \ + && rm -rf /var/lib/apt/lists/* ``` -В Dockerfile обычно объединяют `apt-get update` и `apt-get install` в один layer и чистят cache, чтобы image был меньше. +Разделение `apt-get update` и install по разным cached layers может привести к устаревшим indexes. @@ -629,16 +910,26 @@ apt search package-name **Короткий ответ** -apt-get — более стабильный низкоуровневый CLI, который часто используют в scripts и Dockerfile. apt — более удобный -интерактивный интерфейс для человека, с progress и более дружелюбным выводом. +`apt` — удобный interactive CLI для человека. `apt-get` имеет более стабильный интерфейс и чаще используется в scripts и +Dockerfile. **Полный ответ** -`apt-get` — более стабильный низкоуровневый CLI, который часто используют в scripts и Dockerfile. `apt` — более удобный -интерактивный интерфейс для человека, с progress и более дружелюбным выводом. +Обе команды работают поверх той же package management системы Debian. `apt` объединяет часто используемые возможности +`apt-get` и `apt-cache`, показывает progress и предоставляет более дружелюбный output. + +`apt-get` исторически ориентирован на автоматизацию. Его output и options меньше зависят от interactive terminal, +поэтому он чаще встречается в CI и Dockerfile: + +```bash +apt-get update +apt-get install -y --no-install-recommends curl +``` + +Это не означает, что `apt` нельзя использовать в script, но сама команда может предупреждать, что ее CLI не считается +стабильным для scripting. -Для локальной работы обычно достаточно `apt`. Для automated scripts часто выбирают `apt-get`, потому что его поведение -меньше ориентировано на интерактивность. +На интервью достаточно объяснить разницу назначения: `apt` удобнее вручную, `apt-get` предсказуемее для automation. @@ -652,18 +943,25 @@ apt-get — более стабильный низкоуровневый CLI, к **Короткий ответ** -Linux использует Linux kernel и обычно GNU userland. macOS использует Darwin/XNU kernel и BSD userland. Обе системы -Unix-like, поэтому базовые команды похожи, но опции утилит, filesystem behavior, services, package management и security -model могут отличаться. +Linux использует Linux kernel и обычно GNU userland. macOS построена на Darwin с XNU kernel и BSD userland. Обе системы +Unix-like, но отличаются utilities, filesystem behavior, services, package management и security model. **Полный ответ** -Linux использует Linux kernel и обычно GNU userland. macOS использует Darwin/XNU kernel и BSD userland. Обе системы -Unix-like, поэтому базовые команды похожи, но опции утилит, filesystem behavior, services, package management и security -model могут отличаться. +Сходство дает общий набор concepts: filesystem tree, processes, permissions, shell и POSIX-like APIs. Поэтому +frontend-разработчик может использовать похожие команды на macOS и Linux. -Практический вывод: shell scripts, которые работают в Linux CI, могут ломаться на macOS из-за разных версий `sed`, -`date`, `xargs`, `find`, `grep` и других utilities. +Различия проявляются в деталях: + +- Linux distributions используют разные package managers, macOS обычно дополняют Homebrew; +- GNU и BSD utilities поддерживают разные flags; +- Linux services часто управляются `systemd`, macOS — `launchd`; +- Docker containers используют Linux kernel, даже когда Docker Desktop запущен на macOS через virtual machine; +- default filesystem macOS часто case-insensitive, Linux — case-sensitive; +- системные paths и security restrictions отличаются. + +Практический вывод: macOS удобна как Unix-like developer environment, но не является точной копией Linux production. +Критичные scripts и builds нужно проверять в том окружении, где они будут выполняться, например в Linux CI container. @@ -675,17 +973,36 @@ model могут отличаться. **Короткий ответ** -В Linux часто установлены GNU coreutils, а в macOS — BSD variants. Они реализуют похожие команды, но не всегда -поддерживают одинаковые flags. +Linux часто использует GNU utilities, а macOS — BSD variants. Названия команд похожи, но flags, regular expressions и +формат output могут отличаться. **Полный ответ** -В Linux часто установлены GNU coreutils, а в macOS — BSD variants. Они реализуют похожие команды, но не всегда -поддерживают одинаковые flags. +Стандарт описывает не все расширения CLI utilities. GNU и BSD implementations развивались отдельно и добавляли разные +options. + +Например: -Например, `sed -i` в GNU sed может принимать выражение без backup suffix, а BSD sed на macOS обычно требует явно -передать suffix или пустую строку. Для portable scripts нужно проверять target environment или использовать -кроссплатформенные инструменты вроде Node.js scripts. +```bash +# GNU sed +sed -i 's/old/new/g' file.txt + +# BSD sed в macOS +sed -i '' 's/old/new/g' file.txt +``` + +Различаться могут `date`, `find`, `xargs`, `stat`, `grep` и `readlink`. Script, написанный только под локальную macOS, +может упасть в Linux CI, и наоборот. + +Варианты решения: + +- использовать только переносимое подмножество POSIX; +- явно проверять OS через `uname`; +- устанавливать GNU utilities на macOS; +- заменять сложные shell transformations на Node.js script с tests. + +Кроссплатформенность нужно выбирать осознанно: внутренний Linux-only deploy script не обязан поддерживать macOS, но +project bootstrap для всей команды обычно должен. @@ -697,17 +1014,40 @@ model могут отличаться. **Короткий ответ** -В Linux часто встречаются paths вроде /home/user, /etc, /var/log, /usr/bin. В macOS home directory обычно находится в -/Users/user, а приложения часто живут в /Applications. +В Linux home directory обычно находится в `/home/user`, а в macOS — в `/Users/user`. Также отличаются locations +applications, system config и logs. **Полный ответ** -В Linux часто встречаются paths вроде `/home/user`, `/etc`, `/var/log`, `/usr/bin`. В macOS home directory обычно -находится в `/Users/user`, а приложения часто живут в `/Applications`. +Типичные Linux paths: + +```text +/home/user +/etc +/var/log +/usr/bin +/opt +``` + +Типичные macOS paths: + +```text +/Users/user +/Applications +/Library +/System +/opt/homebrew +``` + +Hardcoded absolute path почти всегда плохо переносится между машинами. В scripts используют `$HOME`, temporary +directories и project-relative paths. + +Существенное отличие — case sensitivity. Default APFS installation macOS часто case-insensitive, поэтому +`import './Button'` может найти `button.ts`. На Linux такой import упадет. -Еще одно отличие — default filesystem behavior. macOS часто использует case-insensitive filesystem, а Linux servers и -Docker images обычно case-sensitive. Поэтому import path с неправильным регистром может работать локально на macOS, но -ломаться в Linux CI. +Кроме того, macOS защищает часть system directories через System Integrity Protection. Даже root не должен изменять их +обычным способом. Developer tools лучше устанавливать в поддерживаемые prefixes, а не копировать binaries вручную в +system locations. @@ -719,14 +1059,32 @@ Docker images обычно case-sensitive. Поэтому import path с неп **Короткий ответ** -systemd — распространенная init/service manager система в Linux. launchd выполняет похожую роль в macOS. +`systemd` — распространенный service manager и init system в Linux. `launchd` управляет daemons и agents в macOS. **Полный ответ** -`systemd` — распространенная init/service manager система в Linux. `launchd` выполняет похожую роль в macOS. +Обе системы запускают background services, следят за lifecycle и могут автоматически стартовать процессы после boot или +login. Но formats и команды у них разные. -Для frontend-разработчика это важно, когда нужно понять, почему service запущен автоматически, как читаются logs, где -настроены daemons и почему инструкция для Linux server не применима напрямую к macOS. +В Linux с `systemd` используют: + +```bash +systemctl status nginx +sudo systemctl restart nginx +journalctl -u nginx +``` + +В macOS `launchd` читает property list files и управляется через `launchctl`. Homebrew services также интегрируются с +`launchd`: + +```bash +brew services start postgresql +``` + +Инструкция `systemctl restart ...` не применима к macOS. Для диагностики нужно сначала понять, кто запустил процесс: +service manager, Docker, IDE, login item или обычный shell. + +Frontend-разработчик сталкивается с этим при локальных databases, reverse proxies, SSR services и CI runners. @@ -741,15 +1099,25 @@ systemd — распространенная init/service manager система **Короткий ответ** Homebrew — package manager, популярный на macOS и доступный на Linux. Он устанавливает CLI tools, libraries и desktop -applications без ручного скачивания архивов и настройки paths. +applications без ручного управления archives и paths. **Полный ответ** -Homebrew — package manager, популярный на macOS и доступный на Linux. Он устанавливает CLI tools, libraries и desktop -applications без ручного скачивания архивов и настройки paths. +Homebrew скачивает готовые bottles или собирает packages по recipes, размещает versions в собственном prefix и создает +symlinks на активные executables. + +Основные области применения: -Для frontend-разработчика Homebrew часто используется для установки `node`, `git`, `pnpm`, `nginx`, `postgresql`, -`watchman`, `jq`, `ripgrep` и других инструментов разработки. +- CLI tools: `git`, `jq`, `ripgrep`, `nginx`; +- libraries и services: `openssl`, `postgresql`, `redis`; +- macOS applications через casks; +- одинаковый developer setup на нескольких machines. + +Homebrew не является частью macOS и не управляет самой операционной системой. Установленные tools могут конфликтовать с +system versions, поэтому важно понимать порядок `PATH`. + +Для командной воспроизводимости одного списка устных инструкций недостаточно. Можно использовать `Brewfile`, version +managers и project bootstrap scripts, но обновления все равно нужно тестировать. @@ -761,11 +1129,11 @@ applications без ручного скачивания архивов и нас **Короткий ответ** -brew install устанавливает package или CLI tool из formula. +`brew install` устанавливает formula и ее dependencies, используя готовый bottle или локальную сборку. **Полный ответ** -`brew install` устанавливает package или CLI tool из formula. +Примеры: ```bash brew install git @@ -773,7 +1141,14 @@ brew install jq brew install ripgrep ``` -Formula описывает, где взять source или binary bottle, какие dependencies нужны и как установить tool в Homebrew prefix. +Homebrew находит formula, выбирает совместимый bottle для OS и architecture, скачивает dependencies и устанавливает +package в Cellar. Затем executable связывается с Homebrew prefix. + +Если bottle недоступен, package может собираться из source, что дольше и требует build tools. После установки +`brew info` показывает version, dependencies и caveats. + +`brew install` без version policy может поставить новую major version после обновления formula. Для project runtime, +например Node.js, часто надежнее version manager, который привязывает version к repository. @@ -785,21 +1160,34 @@ Formula описывает, где взять source или binary bottle, ка **Короткий ответ** -Formula обычно описывает CLI tool или library. Cask описывает macOS application, font или более крупный binary package. -Tap — дополнительный repository с formulae и casks. +Formula описывает CLI tool или library. Cask описывает macOS application, font или binary package. Tap — дополнительный +repository с formulae и casks. **Полный ответ** -Formula обычно описывает CLI tool или library. Cask описывает macOS application, font или более крупный binary package. -Tap — дополнительный repository с formulae и casks. +Formula содержит metadata, source или bottle, dependencies и инструкции установки: ```bash brew install node +``` + +Cask предназначен для applications и других macOS artifacts: + +```bash brew install --cask visual-studio-code +``` + +Tap подключает внешний repository: + +```bash brew tap owner/repository ``` -Для командной разработки чаще используют formulae, для приложений — casks. +После подключения его packages участвуют в обычном поиске и установке. Это удобно для internal tools и packages, которых +нет в Homebrew core. + +Tap является источником executable code, поэтому подключать случайный repository небезопасно. В корпоративной среде +важны review, ownership и обновление сторонних taps. @@ -811,11 +1199,12 @@ brew tap owner/repository **Короткий ответ** -Базовый workflow: +`brew update` обновляет metadata, `brew outdated` показывает устаревшие packages, `brew upgrade` обновляет их, а +`brew cleanup` удаляет старые versions и cache. **Полный ответ** -Базовый workflow: +Типичный workflow: ```bash brew update @@ -824,8 +1213,17 @@ brew upgrade brew cleanup ``` -`brew update` обновляет metadata Homebrew. `brew upgrade` обновляет установленные packages. `brew cleanup` удаляет -старые версии и cache, освобождая место. +`brew update` обновляет definitions formulae и casks, но не установленные packages. `brew upgrade` устанавливает новые +versions. `brew cleanup` освобождает disk space. + +Массовый upgrade может одновременно изменить Node.js, database, compiler и CLI tools. На рабочей машине безопаснее +сначала посмотреть `brew outdated`, обновлять критичные packages отдельно и проверить projects. + +Homebrew не заменяет lockfile приложения: package manager OS фиксирует tools окружения, а `package-lock.json` или +`pnpm-lock.yaml` — JavaScript dependencies. + +Если package временно нельзя обновлять, существуют versioned formulae и pinning, но долгосрочно лучше устранить +несовместимость, а не бесконечно удерживать старую version. @@ -837,7 +1235,7 @@ brew cleanup **Короткий ответ** -Полезные команды: +Для диагностики используют `brew doctor`, `brew config`, `brew info`, `brew list` и проверку `PATH`. **Полный ответ** @@ -848,10 +1246,21 @@ brew doctor brew config brew info node brew list +brew --prefix +command -v node ``` -`brew doctor` проверяет типичные проблемы окружения. `brew info` показывает installed version, dependencies и caveats. -`brew config` полезен, когда нужно понять architecture, prefix и версию Homebrew. +`brew doctor` ищет типичные конфликты permissions, unsupported files и проблемы configuration. Его warnings нужно +оценивать по контексту: не каждый warning блокирует работу. + +`brew config` показывает OS, architecture, developer tools и prefix. Это помогает понять различия Intel и Apple Silicon. +`brew info` показывает active version, dependencies и caveats. + +Частая проблема — package установлен, но shell запускает другой executable. Тогда проверяют `command -v`, `type -a` и +порядок `PATH`. Другая проблема — одновременно установлены version manager и Homebrew version одного runtime. + +Не стоит исправлять Homebrew через случайный `sudo chown -R` без понимания target: можно повредить permissions system +directories или shared machine. @@ -863,16 +1272,31 @@ brew list **Короткий ответ** -На Apple Silicon macOS Homebrew обычно использует prefix /opt/homebrew. На Intel macOS часто используется /usr/local. На -Linux обычно используется /home/linuxbrew/.linuxbrew. +На Apple Silicon macOS Homebrew обычно использует `/opt/homebrew`, на Intel macOS — `/usr/local`, а на Linux — +`/home/linuxbrew/.linuxbrew`. **Полный ответ** -На Apple Silicon macOS Homebrew обычно использует prefix `/opt/homebrew`. На Intel macOS часто используется -`/usr/local`. На Linux обычно используется `/home/linuxbrew/.linuxbrew`. +Конкретный prefix лучше узнавать командой: + +```bash +brew --prefix +brew --prefix node +``` + +Packages хранятся versioned directories внутри Cellar, а active executables доступны через symlinks в `bin`. Такая +структура позволяет Homebrew переключать versions и удалять старые packages. + +Shell должен добавить Homebrew prefix в `PATH`. Рекомендуемую настройку можно получить через: -Из-за этого важен `PATH`: shell должен видеть Homebrew executables раньше или позже системных tools в зависимости от -ожидаемого поведения. +```bash +brew shellenv +``` + +На Apple Silicon и Intel hardcoded path отличается, поэтому bootstrap script не должен без необходимости предполагать +`/usr/local/bin`. + +Если system tool и Homebrew tool имеют одинаковое имя, порядок `PATH` определяет, какой executable будет запущен. @@ -884,16 +1308,22 @@ Linux обычно используется /home/linuxbrew/.linuxbrew. **Короткий ответ** -apt — системный package manager Debian/Ubuntu, тесно связанный с OS repositories и system packages. Homebrew — -user-space package manager, который чаще используют для developer tools и macOS applications. +`apt` — system package manager Debian/Ubuntu, тесно связанный с OS repositories. Homebrew — user-space package manager +для developer tools, libraries и macOS applications. **Полный ответ** -`apt` — системный package manager Debian/Ubuntu, тесно связанный с OS repositories и system packages. Homebrew — -user-space package manager, который чаще используют для developer tools и macOS applications. +`apt` управляет частью Linux system: устанавливает packages в стандартные system paths, интегрируется с security updates +и использует repositories дистрибутива. Для его операций обычно нужны root privileges. + +Homebrew устанавливается в отдельный prefix и часто работает без `sudo`. Он ориентирован на developer tooling и дает +более свежие versions многих utilities. + +На Linux server обычно используют native package manager, потому что он лучше интегрирован с OS lifecycle и security +policy. На developer machine Homebrew удобен для одинакового набора CLI tools на macOS и Linux. -На Linux servers обычно предпочитают системный package manager дистрибутива. На developer machines Homebrew удобен для -получения свежих CLI tools и одинакового setup между macOS и Linux. +Смешивание managers требует осторожности: две версии `openssl`, `python` или `node` могут одновременно существовать в +разных paths, а фактически используемую определит `PATH`. @@ -905,15 +1335,36 @@ user-space package manager, который чаще используют для **Короткий ответ** -Если проекту нужны разные версии Node.js, удобнее использовать version manager: nvm, fnm, volta или похожий инструмент. -Homebrew ставит system-wide developer tool, а version manager позволяет закреплять версию per project. +Если проекты требуют разные версии Node.js, удобнее использовать version manager: `nvm`, `fnm`, `volta` или похожий +инструмент. **Полный ответ** -Если проекту нужны разные версии Node.js, удобнее использовать version manager: `nvm`, `fnm`, `volta` или похожий -инструмент. Homebrew ставит system-wide developer tool, а version manager позволяет закреплять версию per project. +Homebrew хорошо подходит, когда на machine нужна одна актуальная version Node.js. Но frontend-разработчик часто +поддерживает несколько repositories с разными требованиями. + +Version manager позволяет: + +- переключать Node.js per shell или per project; +- читать `.nvmrc` или `.node-version`; +- устанавливать одинаковую version локально и в CI; +- обновлять один project независимо от других. + +Нужно сверять несколько источников: + +```text +.nvmrc +.node-version +package.json -> engines +CI configuration +Dockerfile +``` + +Если они расходятся, локальная успешная сборка не гарантирует успех CI. Homebrew можно использовать для установки самого +version manager, но project runtime лучше закреплять рядом с кодом. -Для командной разработки важно сверять `.nvmrc`, `.node-version`, `engines` в `package.json` и настройки CI. +Volta дополнительно умеет фиксировать package manager и global CLI tools, а `nvm` и `fnm` чаще управляют прежде всего +Node.js versions. Выбор зависит от workflow команды.