Александр Некрасов · Автономное руководство

PHP: полный мануал с примерами, функциями и ООП

Разделы этой страницы
  1. POSIX: процессы, пользователи, права, терминалы и лимиты Unix
  2. POSIX: зачем PHP знать о процессе и его правах
  3. Установка, версии и граница платформы
  4. Быстрый выбор по реальной задаче
  5. Не путать пользователя, процесс, группу и сеанс
  6. Все маски проверки доступа
  7. Все типы узлов mknod
  8. Все ограничения ресурсов и их единицы
  9. Все селекторы sysconf
  10. Все селекторы pathconf и fpathconf
  11. Ошибки, стоимость и правильная интерпретация результата
  12. Полный указатель и задача для закрепления
  13. Функции и методы этой темы
  14. Код и руководство с собой
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 136 · Практика

POSIX: процессы, пользователи, права, терминалы и лимиты Unix

Все41функции POSIX,45констант, диагностика worker, различие UID/GID и PID/PGID, системные ограничения и честная граница Unix.

POSIX: зачем PHP знать о процессе и его правах

Магазин запускает импорт каталога по расписанию. В терминале разработчика он читает файл, а у фонового worker — отказ; другой job исчерпал дескрипторы; несколько одновременно запущенных копий смешали строки журнала. POSIX позволяет спросить ОС: какой это процесс, кто он с точки зрения прав, какие у него группы и ограничения. При специальной необходимости отдельный launcher может изменить часть этих свойств.

Процесс — выполняющаяся программа со своей памятью, открытыми файлами и системной идентичностью. Файл worker.php сам по себе не процесс: два запуска одного файла получат два PID. UID/GID относятся к пользователям ОС, не к пользователям сайта. Изменение переменной $uid не меняет прав; системный вызов posix_setuid просит это сделать ядро, и ядро может отказать.

Путь диагностического вызова
  1. PHP: $pid = posix_getpid()
  2. Расширение POSIX вызывает getpid в ОС
  3. ОС возвращает номер текущего процесса, например4127
  4. PHP сохраняет4127 в $pid
  5. Журнал использует этот номер вместе с отдельным ID запуска
Сначала отличить данные модели от свойств ОССамостоятельный пример
<?php
declare(strict_types=1);

$worker = ['pid' => 4127, 'uid' => 1001, 'job' => 'catalog'];
echo 'Задание ', $worker['job'], ', PID ', $worker['pid'], "\n";
$worker['uid'] = 2000;
echo "Поменяли только число в массиве, права ОС остались прежними\n";
Ожидаемый результат
Задание catalog, PID 4127
Поменяли только число в массиве, права ОС остались прежними

Это маленькая модель с явно выдуманным PID, не настоящий системный вызов. Реальную идентичность читают функции POSIX. Подготовка: переменная, массив, вызов функции.

В карточке имя до скобок — функция; внутри скобок — аргументы. Вызов posix_getpid() не принимает аргументов и возвращает число. В posix_access($path, POSIX_R_OK) путь и именованная маска передаются на вход, на выходе bool. Проверка === false не путает отказ с допустимыми нулевыми значениями. Константа POSIX_R_OK задаёт режим проверки, а не строку для сохранения.

Установка, версии и граница платформы

Расширение POSIX входит в исходники PHP и обычно включено при Unix сборке; его можно отключить --disable-posix. Windows реализация этого расширения не поддерживается. Не путайте с PCRE POSIX character classes, pthreads или PCNTL. Дистрибутив может вынести модуль в отдельный пакет; точное имя пакета зависит от ОС и версии PHP. Наличие PHP8 само по себе не обещает наличие всех системных функций.

Проверяйте расширение в том SAPI, где работает код: CLI и PHP-FPM могут использовать разные бинарники/ini. Команды php --ini и php -m относятся к выбранному CLI. В POSIX нет собственных INI директив, новых resource типов и классов; результаты — числа, bool, строки и массивы. Некоторые функции условно компилируются, потому что libc не предоставляет соответствующего вызова. getrlimit/setsid и подобные системные возможности описаны в этой книге даже там, где исторически не были частью исходного стандарта POSIX.1.

Проверить конкретные возможности без их вызоваПример для указанного окружения
<?php
declare(strict_types=1);

foreach (['posix_getpid', 'posix_geteuid', 'posix_eaccess', 'posix_fpathconf'] as $name) {
    echo $name, ': ', function_exists($name) ? 'есть' : 'нет', "\n";
}
echo 'POSIX_SC_CLK_TCK: ', defined('POSIX_SC_CLK_TCK') ? 'есть' : 'нет', "\n";
Ожидаемый результат
Четыре строки о функциях и строка о константе, по фактической сборке.

Наличие функции проверено до выполнения. На Windows диагностический код работает, но выводит отсутствие POSIX API; он не включает Unix подсистему. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

База примеров — PHP8.5.11. eaccess, sysconf, pathconf, fpathconf и аргумент resource у getrlimit добавлены в8.3; CHILD_MAX/CLK_TCK —8.4; новые проверки аргументов ряда вызовов отмечены в карточках8.5. На Windows выполнены только независимые модели PHP; Unix действия проверены синтаксически и требуют отдельного совместимого CLI стенда. Смена UID/GID/сеанса и лимитов не запускается в рабочем запросе сайта.

Быстрый выбор по реальной задаче

ВопросНужный инструмент
Какой worker написал строку?PID + отдельный ID запуска: posix_getpid.
Чьи права у процесса?Effective UID/GID, supplementary groups; posix_geteuid, posix_getgroups.
Как называется этот UID?Lookup NSS: posix_getpwuid.
Почему cron не пишет файл?Путь CWD, identities, actual fopen error; posix_getcwd, posix_eaccess.
Почему не открывается новый socket?FD budget: posix_getrlimit и утечки незакрытых дескрипторов.
Как уведомить свой worker?Сигнал posix_kill + PCNTL handler; payload через отдельный канал.
Как запретить второй запуск?Менеджер служб или удерживаемый lock. PID existence check недостаточен.
Как измерить CPU?Дельта posix_times / CLK_TCK; latency измеряют отдельно.

Последовательность чтения: наблюдение → диагностика → системные ограничения → изменения в отдельном процессе. Для самого сайта обычно достаточно обычных файловых функций, управления собственным дочерним процессом и сокетов. POSIX выбирают, когда задача действительно связана с Unix процессом, а не потому, что это «более низкий уровень».

Не путать пользователя, процесс, группу и сеанс

ИдентификаторЗначение
PID / PPIDНомер процесса / текущего родителя. Может быть переиспользован после завершения.
PGID / SIDГруппа процессов / сеанс. Не Unix группа пользователей и не $_SESSION.
Real UID/GIDИсходные основные идентичности по правилам ОС.
Effective UID/GIDДействующие основные права для обычных проверок ОС.
Supplementary groupsДополнительные группы уже запущенного процесса.
Saved IDsСохранённые идентичности ОС; возможность возврата зависит от механизма. POSIX PHP не предоставляет здесь универсальный просмотр/сброс всех capabilities.

Модель «пропуск сотрудника» помогает: имя — подпись, UID — номер, группы — дополнительные разрешения. Ограничение аналогии: ACL, namespaces, capabilities и политики ОС сложнее одного пропуска. Один setuid не закрывает открытые раньше файлы и не делает процесс изолированным. Для обычного сервиса предпочтительно назначить пользователя/группы в менеджере служб до запуска PHP.

Все маски проверки доступа

КонстантаДля чего применяется
POSIX_F_OKПроверить существование; значение0, default flags. Не проверяет чтение.
POSIX_R_OKПроверить чтение.
POSIX_W_OKПроверить запись.
POSIX_X_OKПроверить выполнение файла; для каталога — право поиска/прохода.

Флаги объединяют побитовым |. F_OK равен0; добавление его к R_OK не добавляет отдельной возможности. Право и факт существования проверяются в момент вызова; последующая операция обязана обработать свой отказ.

Все типы узлов mknod

КонстантаДля чего применяется
POSIX_S_IFREGОбычный файл; для сайта обычно проще fopen в режиме x.
POSIX_S_IFCHRСимвольное устройство; major/minor выбирают устройство ядра, нужны соответствующие полномочия.
POSIX_S_IFBLKБлочное устройство; не способ создать обычный файл экспорта.
POSIX_S_IFIFOИменованный канал байтов; удобнее posix_mkfifo.
POSIX_S_IFSOCKТип узла Unix socket; наличие узла не создаёт listening socket. Для канала используйте socket/stream API.

Выберите один тип и объедините с восьмеричными правами. Константа может отсутствовать на данной сборке. major/minor относятся к устройствам, а не к permissions. Устройство не требуется для обычного обмена JSON между процессами.

Все ограничения ресурсов и их единицы

КонстантаДля чего применяется
POSIX_RLIMIT_ASВиртуальное адресное пространство процесса, байты; не только память, учтённая PHP memory_limit.
POSIX_RLIMIT_COREРазмер core dump, байты; soft0 запрещает такой файл по RLIMIT_CORE.
POSIX_RLIMIT_CPUCPU секунды; не время ожидания HTTP. Поведение soft/hard и сигналов зависит от ОС.
POSIX_RLIMIT_DATAData segment/heap, байты; взаимодействие с mmap зависит от ОС/версии ядра.
POSIX_RLIMIT_FSIZEПредельный размер создаваемого/увеличиваемого файла, байты. Не размер data segment.
POSIX_RLIMIT_LOCKSОграничение файловых locks/leases там, где ОС реализует его. На Linux историческое, не общий современный ограничитель flock.
POSIX_RLIMIT_MEMLOCKБайты памяти, которую разрешено закрепить в RAM; не общий лимит heap.
POSIX_RLIMIT_MSGQUEUEБюджет POSIX message queues для real UID на поддерживающей ОС. Это не SysV очередь msg_get_queue.
POSIX_RLIMIT_NICEГраница изменения nice priority; Linux кодирует её как20−limit. Не передавайте желаемый отрицательный nice как лимит.
POSIX_RLIMIT_NOFILEГраница: на1 больше максимального допустимого номера дескриптора. Учитывайте файлы, sockets и pipes.
POSIX_RLIMIT_NPROCКоличество процессов/потоков real UID по правилам ОС. Не просто количество PHP jobs одной программы.
POSIX_RLIMIT_RSSResident memory, смысл и действие зависят от ОС. На современном Linux не рабочий способ ограничить RAM; исторический Linux предел измерялся в байтах, не универсальных «страницах».
POSIX_RLIMIT_RTPRIOПредел real-time priority на поддерживающей ОС; не рекомендует включать real-time планирование для сайта.
POSIX_RLIMIT_RTTIMEНа Linux микросекунды CPU real-time процесса без блокирующего системного вызова; не timeout произвольного PHP запроса.
POSIX_RLIMIT_SIGPENDINGПредел очереди сигналов real UID; точные правила доставки/учёта определяет ОС.
POSIX_RLIMIT_STACKМаксимальный стек процесса, байты. Глубина рекурсии PHP дополнительно зависит от движка и расширений.
POSIX_RLIMIT_KQUEUESКоличество kqueue у real UID на поддерживающих BSD; константа PHP8.1+.
POSIX_RLIMIT_NPTSКоличество pseudo-terminals real UID на поддерживающих BSD; PHP8.1+.
POSIX_RLIMIT_INFINITYСимволическое значение отсутствия предела при setrlimit. Не строка "unlimited", которую возвращает getrlimit.

Наличие имени в PHP зависит от headers/ОС. Семантика и фактическое применение некоторых лимитов платформенные. Нельзя выбрать случайное число мегабайт и передать его во все функции: FSIZE ждёт байты, CPU — секунды CPU, RTTIME — иной специальный счётчик. PHP memory_limit, supervisor/container quota и RLIMIT — разные границы.

Все селекторы sysconf

КонстантаДля чего применяется
POSIX_SC_ARG_MAXБюджет argv+environment для запуска программы, байты; нельзя целиком отдать одному аргументу.
POSIX_SC_CHILD_MAXПредел дочерних процессов/процессов real UID по ОС; PHP8.4+.
POSIX_SC_CLK_TCKКоличество clock ticks в секунду для times; PHP8.4+.
POSIX_SC_PAGESIZEРазмер страницы памяти ОС в байтах.
POSIX_SC_NPROCESSORS_CONFКоличество настроенных процессоров.
POSIX_SC_NPROCESSORS_ONLNКоличество процессоров online, не гарантированная CPU quota контейнера.
POSIX_SC_OPEN_MAXПредел открытых дескрипторов sysconf; есть в tagged PHP8.5.11 stub, хотя отдельная страница констант Manual его не перечисляет. Проверяйте defined.

Параметры памяти/CPU появились вместе с sysconf PHP8.3, отдельные новые константы отмечены выше. Недоступное/отрицательное значение не используйте как положительный размер; выбирайте явную политику fallback. Предел argv включает окружение, поэтому большой JSON обычно передают через stdin/файл, а не одним аргументом командной строки.

Все селекторы pathconf и fpathconf

КонстантаДля чего применяется
POSIX_PC_LINK_MAXМаксимум жёстких ссылок на файл.
POSIX_PC_MAX_CANONПредел строки канонического ввода терминала, байты.
POSIX_PC_MAX_INPUTПредел очереди входа терминала, байты.
POSIX_PC_NAME_MAXДлина одного компонента имени в каталоге, байты.
POSIX_PC_PATH_MAXПредел относительного пути для указанного каталога по правилам ОС; не универсальная длина всех абсолютных путей.
POSIX_PC_PIPE_BUFРазмер записи в pipe, для которой ОС гарантирует атомарность при её условиях; не общая ёмкость pipe.
POSIX_PC_CHOWN_RESTRICTEDПризнак ограничений смены владельца/группы; не размер.
POSIX_PC_NO_TRUNCПризнак ошибки вместо усечения слишком длинного имени; не количество символов.
POSIX_PC_ALLOC_SIZE_MINМинимальный размер выделяемого файлового блока в байтах там, где поддерживается.
POSIX_PC_SYMLINK_MAXПредел содержимого символической ссылки в байтах; не количество переходов при разрешении пути.

Все относятся к POSIX pathconf API PHP8.3+. В снимке отдельной страницы Manual ошибочно встречается POSIX_PC_ALLOC_SYMLINK_MAX; в сигнатурной документации и tagged PHP8.5.11 stub правильное имя POSIX_PC_SYMLINK_MAX. Лишнее имя не предлагается как рабочая константа. Для строковых имён файлов считают байты через strlen, а не пользовательские символы через mb_strlen. PIPE_BUF не ёмкость FIFO и не гарантия атомарности произвольной серии fwrite.

Ошибки, стоимость и правильная интерпретация результата

Одинаковый внешне false имеет разный смысл: isattyfalse при перенаправлении — нормальная ветка; getpwuidfalse — не получена запись; accessfalse — проверка не прошла. setsid отказывает значением-1, sysconf также может вернуть-1, но по другой причине. Сохранённый POSIX errno помогает только после wrapper, который действительно его записал; успешный вызов обычно не очищает старую ошибку.

Почему строгое сравнение нужно ещё до системных вызововСамостоятельный пример
<?php
declare(strict_types=1);

$answers = [0, false, -1, 'unlimited'];
foreach ($answers as $answer) {
    echo json_encode($answer), ': ', $answer === false ? 'false' : 'другое значение', "\n";
}
Ожидаемый результат
0: другое значение
false: false
-1: другое значение
"unlimited": другое значение

Модель показывает различие значений. Отдельная карточка задаёт, какое именно из них означает отказ; нельзя придумать один if(!$result) для всех функций.

Стоимость тоже различается: getter PID/UID не эквивалентен NSS lookup, который способен обратиться к сети. Чтение pathconf касается конкретной файловой системы. Не вызывайте десятки системных диагностик в каждом HTTP ответе без необходимости; снимок на запуск worker и отчёт по отказу часто полезнее. При этом кэш имён/групп не должен навсегда скрывать изменение политик. Производительность измеряют в своей среде, а не объявляют «эта функция медленная» без условий.

Полный указатель и задача для закрепления

ПодкатегорияПолный перечень функций
Идентичность и справочники ОСposix_getuid, posix_geteuid, posix_getgid, posix_getegid, posix_getgroups, posix_getlogin, posix_getpwuid, posix_getpwnam, posix_getgrgid, posix_getgrnam
Изменение идентичностиposix_setuid, posix_setgid, posix_seteuid, posix_setegid, posix_initgroups
Процессы, группы, сеансы, сигналыposix_getpid, posix_getppid, posix_getpgrp, posix_getpgid, posix_getsid, posix_setpgid, posix_setsid, posix_kill
Файлы, доступ и терминалыposix_access, posix_eaccess, posix_getcwd, posix_mkfifo, posix_mknod, posix_isatty, posix_ttyname, posix_ctermid
Система, лимиты, счётчики и ошибкиposix_uname, posix_times, posix_getrlimit, posix_setrlimit, posix_sysconf, posix_pathconf, posix_fpathconf, posix_get_last_error, posix_errno, posix_strerror

Учебная задача: worker не читает каталог, и коллега предлагает выполнить chmod777. Сначала составьте локальный отчёт, который показывает текущую директорию, effective UID/GID, состав групп и результат проверки чтения. Не изменяйте права и не выводите полный passwd record. Затем сопоставьте данные с фактическим отказом открытия файла.

Предложенное решение: локальный диагностический отчётПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || !extension_loaded('posix')) throw new RuntimeException('Нужен Unix CLI POSIX');
$path = __DIR__ . '/catalog.txt';
$report = [
    'pid' => posix_getpid(),
    'cwd' => posix_getcwd(),
    'euid' => posix_geteuid(),
    'egid' => posix_getegid(),
    'supplementary_groups' => posix_getgroups(),
];
if (function_exists('posix_eaccess')) $report['effective_read_check'] = posix_eaccess($path, POSIX_R_OK);
echo json_encode($report, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), "\n";
Ожидаемый результат
JSON с текущими процессными данными; без изменения прав.

Если eaccess отсутствует, поле не выдаётся за подтверждённый доступ. CWD/getgroups могут вернутьfalse — отчёт сохраняет это как неизвестное состояние. Дальнейший fopen по-прежнему отдельно обрабатывает отказ. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Следующий шаг: добавьте этот отчёт в локальную диагностику запуска worker, затем сравните CLI и службу с их реальной конфигурацией. Для ограничения параллельных запусков изучите семафоры и процессы либо менеджер задач/удерживаемый файловый lock; для IPC данных — потоки. Не используйте PID из журнала как постоянный адрес процесса.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

posix_getuidУзнать реальный UID процесса: под какой исходной системной идентичностью запущен обработчик. Это число ОС, не ID покупателя из базы сайта.

PHP4+ · posix (Unix)

posix_getuid(): int

Узнать реальный UID процесса: под какой исходной системной идентичностью запущен обработчик. Это число ОС, не ID покупателя из базы сайта.

Часть вызоваОбъяснение
Сигнатураposix_getuid(): int
ВходНет параметров; пустые скобки запускают получение значения.
Результат и отказЦелый real UID; 0 — допустимый UID root, а не false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Обычно real и effective UID одинаковы, но при изменении привилегий могут различаться. Для проверки текущих файловых прав рассматривайте effective UID, группы, ACL и другие ограничения ОС.

Прочитать UID в переменнуюПример для указанного окружения
<?php
declare(strict_types=1);

$uid = posix_getuid();
echo 'Real UID: ', $uid, "\n";
Ожидаемый результат
Например Real UID: 1000; значение относится к текущему процессу.

Сначала ОС вернула число; оператор = сохранил его в $uid; echo показывает значение. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Диагностировать различие идентичностейПример для указанного окружения
<?php
declare(strict_types=1);

$real = posix_getuid();
$effective = posix_geteuid();
echo $real === $effective ? "UID совпадают\n" : "UID различаются\n";
Ожидаемый результат
UID совпадают либо UID различаются.

Такой отчёт помогает понять запуск через привилегированный wrapper. Он не доказывает, кто вошёл на сайт, и не является полной проверкой доступа. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_geteuid, posix_getpwuid.

posix_geteuidПонять, с чьими текущими правами работает импорт каталога и почему ему отказано в записи.

PHP4+ · posix (Unix)

posix_geteuid(): int

Понять, с чьими текущими правами работает импорт каталога и почему ему отказано в записи.

Часть вызоваОбъяснение
Сигнатураposix_geteuid(): int
ВходНет.
Результат и отказEffective UID как int; 0 не означает ошибку.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

get_current_user сообщает владельца PHP файла, а не текущую эффективную идентичность. getenv(USER), LOGNAME и SUDO_USER — окружение, не авторитетное доказательство прав.

Узнать действующий UID без shellПример для указанного окружения
<?php
declare(strict_types=1);

echo 'Effective UID: ', posix_geteuid(), "\n";
Ожидаемый результат
Строка с фактическим effective UID.

Не запускаем whoami через exec ради уже доступного системного вызова. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Не запускать обычный импорт с root UIDПример для указанного окружения
<?php
declare(strict_types=1);

if (posix_geteuid() === 0) {
    fwrite(STDERR, "Импорт должен работать от отдельной непривилегированной учётной записи\n");
    exit(1);
}
echo "UID подходит для обычного запуска\n";
Ожидаемый результат
Для UID0 — сообщение в stderr и код1; для другого UID — строка об обычном запуске.

Это конкретная политика job, не утверждение, что любое ненулевое значение гарантирует отсутствие Linux capabilities или полный sandbox. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getuid, posix_getpwuid, posix_seteuid.

posix_getgidПрочитать реальный основной GID процесса при разборе прав сервисной учётной записи.

PHP4+ · posix (Unix)

posix_getgid(): int

Прочитать реальный основной GID процесса при разборе прав сервисной учётной записи.

Часть вызоваОбъяснение
Сигнатураposix_getgid(): int
ВходНет.
Результат и отказЦелый real GID, в том числе 0.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Основная группа — только часть идентичности. Дополнительные группы читаются отдельно; GID не обозначает роль администратора сайта.

Прочитать номер исходной группыПример для указанного окружения
<?php
declare(strict_types=1);

$gid = posix_getgid();
echo 'Real GID: ', $gid, "\n";
Ожидаемый результат
Строка с реальным GID.

Число можно сохранить в диагностике запуска. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Показать название основной группыПример для указанного окружения
<?php
declare(strict_types=1);

$gid = posix_getgid();
$group = posix_getgrgid($gid);
echo $group === false ? "Нет записи группы для GID $gid\n" : 'Группа: ' . $group['name'] . "\n";
Ожидаемый результат
Название найденной системной группы либо явное сообщение об отсутствии записи.

Процесс может иметь числовую группу, для которой нет записи в доступной NSS базе, например внутри контейнера. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getegid, posix_getgroups, posix_getgrgid.

posix_getegidУзнать текущую основную группу, участвующую в проверке прав процесса.

PHP4+ · posix (Unix)

posix_getegid(): int

Узнать текущую основную группу, участвующую в проверке прав процесса.

Часть вызоваОбъяснение
Сигнатураposix_getegid(): int
ВходНет.
Результат и отказEffective GID как int.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Добавление пользователя в группу в системной базе не меняет автоматически уже запущенный worker: новый состав групп обычно получают при новом запуске.

Прочитать эффективную группуПример для указанного окружения
<?php
declare(strict_types=1);

echo 'Effective GID: ', posix_getegid(), "\n";
Ожидаемый результат
Строка с effective GID.

Сравнивайте с владельцем/группой каталога при разборе отказа записи. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Собрать группы, доступные текущему процессуПример для указанного окружения
<?php
declare(strict_types=1);

$extra = posix_getgroups();
if ($extra === false) throw new RuntimeException('Не прочитаны дополнительные группы');
$groups = array_values(array_unique([posix_getegid(), ...$extra]));
echo implode(', ', $groups), "\n";
Ожидаемый результат
Уникальные числовые GID текущего процесса.

getgroups не обязан включать основную эффективную группу на каждой ОС, поэтому добавляем её явно. Это диагностика; ACL и особенности файловой системы всё ещё имеют значение. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getgid, posix_getgroups, posix_setegid.

posix_getgroupsПосмотреть дополнительные группы уже работающего импортёра: почему новое членство из настроек ОС ещё не действует.

PHP4+ · posix (Unix)

posix_getgroups(): array|false

Посмотреть дополнительные группы уже работающего импортёра: почему новое членство из настроек ОС ещё не действует.

Часть вызоваОбъяснение
Сигнатураposix_getgroups(): array|false
ВходНет.
Результат и отказСписок целых GID либо false. Пустой список допустим.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Список принадлежит процессу, а не произвольно выбранному имени пользователя. Не заменяет его чтение поля members одной группы: там могут отсутствовать пользователи с этой группой в качестве основной.

Получить дополнительные группыПример для указанного окружения
<?php
declare(strict_types=1);

$groups = posix_getgroups();
if ($groups === false) throw new RuntimeException('Группы недоступны');
echo 'Дополнительных групп: ', count($groups), "\n";
Ожидаемый результат
Дополнительных групп: N.

Проверка === false сохраняет различие между отказом и нормальным пустым массивом. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Проверить членство процесса в группе экспортаПример для указанного окружения
<?php
declare(strict_types=1);

$target = posix_getgrnam('catalog-export');
if ($target === false) throw new RuntimeException('На стенде нужна группа catalog-export');
$groups = posix_getgroups();
if ($groups === false) throw new RuntimeException('Не прочитаны группы процесса');
$member = in_array($target['gid'], [posix_getegid(), ...$groups], true);
echo $member ? "Группа экспорта присутствует\n" : "Нужен запуск с нужным составом групп\n";
Ожидаемый результат
Одна из двух строк о членстве; при отсутствии настроенной группы — исключение.

Проверяем собственную сервисную среду перед экспортом. Это не обещает успешного fopen: фактическая операция тоже должна обработать отказ. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getegid, posix_getgrnam, posix_initgroups.

posix_getloginПолучить имя терминального входа для локальной CLI диагностики, понимая, почему в cron оно часто недоступно.

PHP4+ · posix (Unix)

posix_getlogin(): string|false

Получить имя терминального входа для локальной CLI диагностики, понимая, почему в cron оно часто недоступно.

Часть вызоваОбъяснение
Сигнатураposix_getlogin(): string|false
ВходНет.
Результат и отказИмя login session либо false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Underlying getlogin относится к терминальному входу и не является надёжным именем effective UID; daemon, контейнер и cron могут не иметь login record. Не используйте это значение для авторизации.

Нормально обработать отсутствие сеанса входаПример для указанного окружения
<?php
declare(strict_types=1);

$login = posix_getlogin();
echo $login === false ? "Терминальный login недоступен\n" : "Login: $login\n";
Ожидаемый результат
Имя login либо сообщение об отсутствии.

Отсутствие записи у фонового job не означает, что ОС не знает его UID. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Различить терминальный вход и эффективного пользователяПример для указанного окружения
<?php
declare(strict_types=1);

$login = posix_getlogin();
$account = posix_getpwuid(posix_geteuid());
echo 'Login session: ', $login === false ? 'нет' : $login, "\n";
echo 'Effective account: ', $account === false ? 'нет записи' : $account['name'], "\n";
Ожидаемый результат
Две подписанные строки; значения могут различаться.

При sudo терминальный login и действующая учётная запись — разные вопросы. Нельзя молча выдавать одно за другое. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_geteuid, posix_getpwuid.

posix_getpwuidПреобразовать числовой UID worker в понятное имя и получить профиль системной учётной записи.

PHP4+ · posix (Unix)

posix_getpwuid(int $user_id): array|false

Преобразовать числовой UID worker в понятное имя и получить профиль системной учётной записи.

Часть вызоваОбъяснение
Сигнатураposix_getpwuid(int $user_id): array|false
ВходUID как int, полученный из ОС или проверенной конфигурации.
Результат и отказАссоциативный массив либо false при отсутствии записи/ошибке.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Числовой UID может быть действительным для процесса и отсутствовать в NSS. Ошибка не всегда означает ненулевой свежий errno; не делайте вывода «пользователя точно нет» только по старому posix_get_last_error.

Запись пользователя содержит name (имя), uid/gid (числа), gecos (описание), dir (домашний каталог), shell (login shell), passwd (обычно маркер x/*, не открытый пароль). В tagged PHP8.5 строковые поля могут быть null, если libc не предоставила их. Эти данные не проверяют пароль и не должны публиковаться целиком. Источник — системная база через NSS: это может быть LDAP/другая служба, а не только /etc/passwd; lookup может ждать сеть. Повторные запросы в цикле лучше убрать или кэшировать ограниченно.

Подписать собственный workerПример для указанного окружения
<?php
declare(strict_types=1);

$uid = posix_geteuid();
$account = posix_getpwuid($uid);
echo $account === false ? "Worker UID=$uid без записи NSS\n" : 'Worker: ' . $account['name'] . "\n";
Ожидаемый результат
Имя worker либо числовой UID без найденной записи.

UID остаётся полезным даже при неудачном преобразовании в имя. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Отличить HOME окружения от системной записиПример для указанного окружения
<?php
declare(strict_types=1);

$account = posix_getpwuid(posix_geteuid());
if ($account === false) throw new RuntimeException('Нет системной записи');
$home = $account['dir'];
if (!is_string($home) || $home === '') throw new RuntimeException('Домашний каталог не задан');
echo 'Каталог в NSS: ', $home, "\n";
echo 'HOME окружения: ', getenv('HOME') === false ? 'не задан' : getenv('HOME'), "\n";
Ожидаемый результат
Две строки с каталогами; они могут различаться.

Чтение dir не создаёт каталог и не выдаёт права. Для состояния сервиса чаще задают отдельный абсолютный путь в конфигурации. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpwnam, posix_geteuid.

posix_getpwnamНайти заранее настроенную сервисную учётную запись по имени перед запуском фонового задания.

PHP4+ · posix (Unix)

posix_getpwnam(string $username): array|false

Найти заранее настроенную сервисную учётную запись по имени перед запуском фонового задания.

Часть вызоваОбъяснение
Сигнатураposix_getpwnam(string $username): array|false
ВходСистемное имя; это не email и не аккаунт сайта.
Результат и отказЗапись пользователя со всеми полями ниже либо false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Не существует универсального лимита «16 символов» для всех NSS реализаций. Не передавайте непроверенные значения с NUL; поиск не создаёт пользователя и не подтверждает владение аккаунтом.

Запись пользователя содержит name (имя), uid/gid (числа), gecos (описание), dir (домашний каталог), shell (login shell), passwd (обычно маркер x/*, не открытый пароль). В tagged PHP8.5 строковые поля могут быть null, если libc не предоставила их. Эти данные не проверяют пароль и не должны публиковаться целиком. Источник — системная база через NSS: это может быть LDAP/другая служба, а не только /etc/passwd; lookup может ждать сеть. Повторные запросы в цикле лучше убрать или кэшировать ограниченно.

Прочитать конфигурационное имяПример для указанного окружения
<?php
declare(strict_types=1);

$account = posix_getpwnam('catalog-worker');
if ($account === false) throw new RuntimeException('Настройте catalog-worker на учебном стенде');
echo 'UID=', $account['uid'], '; GID=', $account['gid'], "\n";
Ожидаемый результат
UID и GID настроенной учётной записи либо исключение.

Имя выбрано администратором в конфигурации, не получено из формы посетителя. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Проверить согласованность собственной записиПример для указанного окружения
<?php
declare(strict_types=1);

$current = posix_getpwuid(posix_geteuid());
if ($current === false || !is_string($current['name'])) throw new RuntimeException('Нет имени');
$byName = posix_getpwnam($current['name']);
echo $byName !== false && $byName['uid'] === $current['uid']
    ? "Имя и UID согласованы\n" : "Запись изменилась или lookup не удался\n";
Ожидаемый результат
Строка о согласованности либо изменении/отказе.

Два lookup не образуют транзакцию: каталог пользователей может изменяться. Не используйте roundtrip как процедуру входа на сайт. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpwuid, posix_initgroups, posix_setuid.

posix_getgrgidПодписать числовые группы процесса человекочитаемыми именами в локальном отчёте.

PHP4+ · posix (Unix)

posix_getgrgid(int $group_id): array|false

Подписать числовые группы процесса человекочитаемыми именами в локальном отчёте.

Часть вызоваОбъяснение
Сигнатураposix_getgrgid(int $group_id): array|false
ВходGID как int.
Результат и отказМассив записи либо false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Проверяйте false до доступа по ключам. Отсутствие имени не обнуляет идентификатор группы и не снимает её права.

Поля группы: name, passwd, gid, members — список имён. passwd обычно служебный маркер. members перечисляет записанное членство, но не обязательно всех пользователей, у которых этот GID основной. База может быть сетевой, поэтому lookup не стоит повторять для каждой строки большого отчёта.

Название действующей основной группыПример для указанного окружения
<?php
declare(strict_types=1);

$gid = posix_getegid();
$group = posix_getgrgid($gid);
echo $group === false ? "GID=$gid\n" : $group['name'] . "\n";
Ожидаемый результат
Имя группы либо GID=N.

Показан явный запасной вариант без потери числовой идентичности. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Отчёт по уникальным группам без повторных lookupПример для указанного окружения
<?php
declare(strict_types=1);

$extra = posix_getgroups();
if ($extra === false) throw new RuntimeException('Группы недоступны');
foreach (array_unique([posix_getegid(), ...$extra]) as $gid) {
    $group = posix_getgrgid($gid);
    echo $gid, ': ', $group === false ? '(нет записи)' : $group['name'], "\n";
}
Ожидаемый результат
Одна строка GID: имя для каждой уникальной группы.

Сначала устраняем повторы, затем обращаемся к NSS. Это отчёт владельцу сервиса, а не публичная страница. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getgroups, posix_getgrnam.

posix_getgrnamПолучить номер настроенной группы каталога по понятному имени.

PHP4+ · posix (Unix)

posix_getgrnam(string $name): array|false

Получить номер настроенной группы каталога по понятному имени.

Часть вызоваОбъяснение
Сигнатураposix_getgrnam(string $name): array|false
ВходИмя группы ОС.
Результат и отказМассив name/passwd/gid/members либо false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это чтение системного справочника, не изменение групп процесса. Сравнение members с именем не заменяет getgroups для проверки действующего worker.

Поля группы: name, passwd, gid, members — список имён. passwd обычно служебный маркер. members перечисляет записанное членство, но не обязательно всех пользователей, у которых этот GID основной. База может быть сетевой, поэтому lookup не стоит повторять для каждой строки большого отчёта.

Найти группу экспортаПример для указанного окружения
<?php
declare(strict_types=1);

$group = posix_getgrnam('catalog-export');
if ($group === false) throw new RuntimeException('Группа catalog-export недоступна');
echo 'GID экспорта: ', $group['gid'], "\n";
Ожидаемый результат
Строка с GID либо исключение при отсутствии настройки.

Числовой GID затем может использовать доверенный launcher, а не посетитель сайта. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Показать записанный список участниковПример для указанного окружения
<?php
declare(strict_types=1);

$group = posix_getgrnam('catalog-export');
if ($group === false) throw new RuntimeException('Нет записи группы');
echo 'Явных записей members: ', count($group['members']), "\n";
foreach ($group['members'] as $member) echo $member, "\n";
Ожидаемый результат
Количество и имена из members; пустой список возможен.

Это именно содержимое записи. Пользователь с основной группой catalog-export может не оказаться в members; в уроке не делаем ошибочный отказ доступа из такого отсутствия. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getgrgid, posix_getgroups, posix_setgid.

posix_setuidПосле ограниченной стартовой операции передать дальнейшую работу отдельной сервисной идентичности.

PHP4+ · posix (Unix)

posix_setuid(int $user_id): bool

После ограниченной стартовой операции передать дальнейшую работу отдельной сервисной идентичности.

Часть вызоваОбъяснение
Сигнатураposix_setuid(int $user_id): bool
ВходЦелый UID из доверенной системной записи, не из HTTP запроса.
Результат и отказtrue — системный вызов выполнен; false — отказ, обычно с errno.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

На Linux привилегированный setuid меняет real/effective/saved UID; такой сброс обычно необратим. Непривилегированный процесс ограничен разрешёнными real/saved UID. Вызов не назначает основные или дополнительные группы автоматически. Проверяйте отказ даже при UID0.

Меняется идентичность всего процесса, не отдельной PHP переменной. Поэтому такие вызовы нельзя вставлять в обработчик посетителя внутри долгоживущего PHP-FPM worker. Обычный сайт запускают сразу с назначенными сервисными правами. Привилегированный launcher — отдельная задача администрирования: закрытие лишних дескрипторов, окружение, capabilities и ограничения контейнера тоже требуют настройки. Набор ниже показывает конкретный механизм UID/GID, а не универсальный sandbox.

Минимальный вызов с собственным UIDПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен отдельный CLI');
$uid = posix_getuid();
if (!posix_setuid($uid)) throw new RuntimeException('ОС отклонила setuid');
echo 'Effective UID после вызова: ', posix_geteuid(), "\n";
Ожидаемый результат
Текущий effective UID либо исключение при отказе ОС.

Пример без выбора чужого пользователя. Даже установка своего UID не является переносимой гарантией успешности на любой системе. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Настроить группы, затем окончательно UIDПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || posix_geteuid() !== 0) {
    throw new RuntimeException('Только отдельный привилегированный учебный launcher');
}
$account = posix_getpwnam('catalog-worker');
if ($account === false || $account['uid'] === 0 || $account['gid'] === 0) {
    throw new RuntimeException('Нужна настроенная непривилегированная учётная запись');
}
if (!posix_initgroups($account['name'], $account['gid'])) {
    throw new RuntimeException('Не назначены дополнительные группы');
}
if (!posix_setgid($account['gid'])) throw new RuntimeException('Не назначен GID');
if (!posix_setuid($account['uid'])) throw new RuntimeException('Не назначен UID');
if (posix_geteuid() !== $account['uid'] || posix_getegid() !== $account['gid']) {
    throw new RuntimeException('Идентичность не совпала');
}
echo "Учебный launcher перешёл к идентичности worker\n";
Ожидаемый результат
При успешной настройке: Учебный launcher перешёл к идентичности worker.

Последовательность initgroups → setgid → setuid оставляет необходимые стартовые полномочия до настройки групп. Любая ошибка останавливает дальнейший запуск, вместо продолжения с неожиданными правами. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getuid, posix_geteuid, posix_setgid, posix_initgroups.

posix_setgidНазначить основную группу фонового процесса до отказа от стартовых привилегий.

PHP4+ · posix (Unix)

posix_setgid(int $group_id): bool

Назначить основную группу фонового процесса до отказа от стартовых привилегий.

Часть вызоваОбъяснение
Сигнатураposix_setgid(int $group_id): bool
ВходЦелый GID.
Результат и отказtrue либо false; проверить отказ до продолжения работы.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

У привилегированного процесса Linux меняет real/effective/saved GID. Дополнительные группы сохраняются, если не назначить их отдельно. Поэтому один setgid не удаляет старые групповые полномочия.

Меняется идентичность всего процесса, не отдельной PHP переменной. Поэтому такие вызовы нельзя вставлять в обработчик посетителя внутри долгоживущего PHP-FPM worker. Обычный сайт запускают сразу с назначенными сервисными правами. Привилегированный launcher — отдельная задача администрирования: закрытие лишних дескрипторов, окружение, capabilities и ограничения контейнера тоже требуют настройки. Набор ниже показывает конкретный механизм UID/GID, а не универсальный sandbox.

Самый короткий вызов с реальным GIDПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен отдельный CLI');
$gid = posix_getgid();
if (!posix_setgid($gid)) throw new RuntimeException('ОС отклонила GID');
echo 'Effective GID: ', posix_getegid(), "\n";
Ожидаемый результат
Строка с GID либо отказ.

Скобки получают одно число; проверка bool относится к операции, а не к числовому GID0. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Основная группа в полном launcherПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || posix_geteuid() !== 0) {
    throw new RuntimeException('Только отдельный привилегированный учебный launcher');
}
$account = posix_getpwnam('catalog-worker');
if ($account === false || $account['uid'] === 0 || $account['gid'] === 0) {
    throw new RuntimeException('Нужна настроенная непривилегированная учётная запись');
}
if (!posix_initgroups($account['name'], $account['gid'])) {
    throw new RuntimeException('Не назначены дополнительные группы');
}
if (!posix_setgid($account['gid'])) throw new RuntimeException('Не назначен GID');
if (!posix_setuid($account['uid'])) throw new RuntimeException('Не назначен UID');
if (posix_geteuid() !== $account['uid'] || posix_getegid() !== $account['gid']) {
    throw new RuntimeException('Идентичность не совпала');
}
echo "Учебный launcher перешёл к идентичности worker\n";
Ожидаемый результат
При успехе — строка о переходе к worker.

Основной GID выбран из passwd записи, а дополнительные группы назначены отдельно. Копируемая программа полностью показывает порядок; после завершения одноразового процесса изменения исчезают вместе с ним. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getgid, posix_getegid, posix_initgroups, posix_setuid.

posix_seteuidИзменить именно effective UID в специальном launcher, сохранив различие между текущими и сохранёнными полномочиями.

PHP4+ · posix (Unix)

posix_seteuid(int $user_id): bool

Изменить именно effective UID в специальном launcher, сохранив различие между текущими и сохранёнными полномочиями.

Часть вызоваОбъяснение
Сигнатураposix_seteuid(int $user_id): bool
ВходЦелый effective UID, разрешённый ОС.
Результат и отказtrue либо false; функция зависит от поддержки seteuid при сборке.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это не равнозначно окончательному сбросу всех привилегий. На Linux допускаются real/effective/saved UID или переход при CAP_SETUID; обычный worker не может выбрать произвольного пользователя. Мы не оставляем привилегированный PHP-FPM между запросами.

Меняется идентичность всего процесса, не отдельной PHP переменной. Поэтому такие вызовы нельзя вставлять в обработчик посетителя внутри долгоживущего PHP-FPM worker. Обычный сайт запускают сразу с назначенными сервисными правами. Привилегированный launcher — отдельная задача администрирования: закрытие лишних дескрипторов, окружение, capabilities и ограничения контейнера тоже требуют настройки. Набор ниже показывает конкретный механизм UID/GID, а не универсальный sandbox.

Попытаться установить уже действующий UIDПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен CLI');
$effective = posix_geteuid();
echo posix_seteuid($effective) ? "Вызов принят\n" : "ОС отклонила вызов\n";
Ожидаемый результат
Вызов принят либо ОС отклонила вызов.

Некоторые POSIX реализации могут отклонять даже установку текущего значения. Результат не игнорируется. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Перейти к real UID и увидеть, что real не менялсяПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен CLI');
$real = posix_getuid();
if (!posix_seteuid($real)) throw new RuntimeException('Не изменён effective UID');
echo 'Real=', posix_getuid(), '; effective=', posix_geteuid(), "\n";
Ожидаемый результат
Real и effective показывают исходный real UID.

На обычном непривилегированном запуске числа и так одинаковы. На специальном set-ID запуске это может снизить effective права, но saved UID и другие привилегии нельзя считать удалёнными. Для окончательного сброса см. setuid. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_geteuid, posix_getuid, posix_setuid.

posix_setegidИзменить эффективную основную группу процесса без обещания смены всей групповой идентичности.

PHP4+ · posix (Unix)

posix_setegid(int $group_id): bool

Изменить эффективную основную группу процесса без обещания смены всей групповой идентичности.

Часть вызоваОбъяснение
Сигнатураposix_setegid(int $group_id): bool
ВходЦелый GID, допускаемый ОС.
Результат и отказtrue или false; доступность зависит от сборки.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Смена effective GID не пересчитывает дополнительные группы. В частности, простое членство в supplementary group не всегда разрешает setegid на её номер: правила setegid опираются на real/effective/saved GID и привилегии.

Меняется идентичность всего процесса, не отдельной PHP переменной. Поэтому такие вызовы нельзя вставлять в обработчик посетителя внутри долгоживущего PHP-FPM worker. Обычный сайт запускают сразу с назначенными сервисными правами. Привилегированный launcher — отдельная задача администрирования: закрытие лишних дескрипторов, окружение, capabilities и ограничения контейнера тоже требуют настройки. Набор ниже показывает конкретный механизм UID/GID, а не универсальный sandbox.

Явно проверить результат назначения EGIDПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен CLI');
$gid = posix_getegid();
if (!posix_setegid($gid)) throw new RuntimeException('EGID не установлен');
echo 'EGID=', posix_getegid(), "\n";
Ожидаемый результат
EGID=N либо исключение.

Не подменяем успешность предположением «это же текущая группа». Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Вернуться к real GID в одноразовом процессеПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен CLI');
$real = posix_getgid();
$before = posix_getgroups();
if (!posix_setegid($real)) throw new RuntimeException('Группа не изменена');
$after = posix_getgroups();
echo 'EGID=', posix_getegid(), "\n";
echo $before !== false && $after !== false && $before === $after
    ? "Дополнительные группы не изменились\n" : "Проверьте состав групп\n";
Ожидаемый результат
Новый EGID и строка о дополнительных группах.

Так видно, что основной GID и список дополнительных групп — разные свойства процесса. Для пересчёта списка есть initgroups. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getegid, posix_setgid, posix_getgroups, posix_initgroups.

posix_initgroupsНазначить процессу дополнительные группы выбранной учётной записи при подготовке отдельного worker.

PHP5.2+ · posix (Unix)

posix_initgroups(string $username, int $group_id): bool

Назначить процессу дополнительные группы выбранной учётной записи при подготовке отдельного worker.

Часть вызоваОбъяснение
Сигнатураposix_initgroups(string $username, int $group_id): bool
Входusername — системное имя; group_id — базовый GID, который также включается.
Результат и отказtrue при успехе, false при отказе или пустом имени.
Среда и версияPHP5.2+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Функция не просто вычисляет массив: libc меняет supplementary groups процесса и обычно требует CAP_SETGID/root. В PHP8.5.11 wrapper не записывает новый POSIX last_error после initgroups, поэтому старый errno не выдаём за причину этого отказа.

Меняется идентичность всего процесса, не отдельной PHP переменной. Поэтому такие вызовы нельзя вставлять в обработчик посетителя внутри долгоживущего PHP-FPM worker. Обычный сайт запускают сразу с назначенными сервисными правами. Привилегированный launcher — отдельная задача администрирования: закрытие лишних дескрипторов, окружение, capabilities и ограничения контейнера тоже требуют настройки. Набор ниже показывает конкретный механизм UID/GID, а не универсальный sandbox.

Увидеть изменение списка в изолированном launcherПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || posix_geteuid() !== 0) throw new RuntimeException('Нужен отдельный привилегированный стенд');
$account = posix_getpwnam('catalog-worker');
if ($account === false || $account['uid'] === 0) throw new RuntimeException('Нет непривилегированного worker');
if (!posix_initgroups($account['name'], $account['gid'])) throw new RuntimeException('initgroups не выполнен');
$groups = posix_getgroups();
if ($groups === false) throw new RuntimeException('Список не прочитан');
echo 'Назначено дополнительных GID: ', count($groups), "\n";
Ожидаемый результат
Количество назначенных групп либо явный отказ.

Эта отдельная демонстрация заканчивается сразу: она ещё не сменила UID и не запускает обработку данных. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Использовать назначение групп в полном сбросе правПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || posix_geteuid() !== 0) {
    throw new RuntimeException('Только отдельный привилегированный учебный launcher');
}
$account = posix_getpwnam('catalog-worker');
if ($account === false || $account['uid'] === 0 || $account['gid'] === 0) {
    throw new RuntimeException('Нужна настроенная непривилегированная учётная запись');
}
if (!posix_initgroups($account['name'], $account['gid'])) {
    throw new RuntimeException('Не назначены дополнительные группы');
}
if (!posix_setgid($account['gid'])) throw new RuntimeException('Не назначен GID');
if (!posix_setuid($account['uid'])) throw new RuntimeException('Не назначен UID');
if (posix_geteuid() !== $account['uid'] || posix_getegid() !== $account['gid']) {
    throw new RuntimeException('Идентичность не совпала');
}
echo "Учебный launcher перешёл к идентичности worker\n";
Ожидаемый результат
При успехе — строка о переходе к worker.

Если сначала сделать setuid, может не хватить полномочий для initgroups. Новый запуск по системной конфигурации обычно проще и надёжнее ручного переключения в приложении. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getgroups, posix_getpwnam, posix_setgid, posix_setuid.

posix_getpidДобавить номер worker к журналу, чтобы отличать одновременно работающие импорты.

PHP4+ · posix (Unix)

posix_getpid(): int

Добавить номер worker к журналу, чтобы отличать одновременно работающие импорты.

Часть вызоваОбъяснение
Сигнатураposix_getpid(): int
ВходНет.
Результат и отказPID текущего процесса как int.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

PID не уникален навсегда: после завершения ОС может назначить его другой программе. В контейнере число относится к PID namespace. PID файла самого по себе недостаточно для надёжной блокировки повторного запуска.

Прочитать номер процессаПример для указанного окружения
<?php
declare(strict_types=1);

$pid = posix_getpid();
echo 'Worker PID: ', $pid, "\n";
Ожидаемый результат
Worker PID: N.

Это номер выполняющегося PHP процесса, а не номер заказа. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Пометить несколько событий одного запускаПример для указанного окружения
<?php
declare(strict_types=1);

$run = bin2hex(random_bytes(6));
$pid = posix_getpid();
foreach (['start', 'catalog-loaded', 'done'] as $event) {
    echo json_encode(['run' => $run, 'pid' => $pid, 'event' => $event], JSON_THROW_ON_ERROR), "\n";
}
Ожидаемый результат
Три JSON строки с одинаковыми run и pid, разными event.

Случайный run отделяет разные запуски даже при повторном использовании PID. Для запрета второго job используйте lock/supervisor; журнал не является замком. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getppid, posix_getpgrp, posix_kill.

posix_getppidУвидеть, какой процесс сейчас считается родителем PHP worker, при разборе запуска cron/supervisor.

PHP4+ · posix (Unix)

posix_getppid(): int

Увидеть, какой процесс сейчас считается родителем PHP worker, при разборе запуска cron/supervisor.

Часть вызоваОбъяснение
Сигнатураposix_getppid(): int
ВходНет.
Результат и отказТекущий parent PID.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

После смерти родителя процесс может быть переподчинён; в PID namespace возможен PPID0. PPID не обязательно PID shell, который вы видите, и не доказывает доверенность запуска.

Посмотреть пару PID/PPIDПример для указанного окружения
<?php
declare(strict_types=1);

echo 'PID=', posix_getpid(), '; PPID=', posix_getppid(), "\n";
Ожидаемый результат
Два фактических номера процесса и родителя.

Лог помогает найти дерево запуска без выполнения ps. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Сохранить происхождение job в диагностикеПример для указанного окружения
<?php
declare(strict_types=1);

$startedBy = posix_getppid();
$events = ['read-config', 'validate-job'];
foreach ($events as $event) echo $event, ': parent-at-start=', $startedBy, "\n";
echo 'parent-now=', posix_getppid(), "\n";
Ожидаемый результат
События с первоначальным PPID и отдельное текущее значение.

Сохранённое число — снимок. Нельзя отправлять сигнал «родителю при старте» намного позже без учёта его завершения и повторного использования PID. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpid, posix_getpgid.

posix_getpgrpУзнать группу процессов своего job: терминал и supervisor могут управлять группой целиком.

PHP4+ · posix (Unix)

posix_getpgrp(): int

Узнать группу процессов своего job: терминал и supervisor могут управлять группой целиком.

Часть вызоваОбъяснение
Сигнатураposix_getpgrp(): int
ВходНет.
Результат и отказТекущий process group ID, PGID.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Группа процессов не равна Unix группе пользователей GID. В одной PGID могут находиться PHP, shell и другие программы конвейера; необдуманный сигнал группе затронет их все.

Различить PID и PGIDПример для указанного окружения
<?php
declare(strict_types=1);

echo 'PID=', posix_getpid(), '; PGID=', posix_getpgrp(), "\n";
Ожидаемый результат
Два числа, которые могут совпасть или отличаться.

Совпадение PID и PGID означает лидерство группы, а не повышенные права. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Проверить предпосылку создания сеансаПример для указанного окружения
<?php
declare(strict_types=1);

$leader = posix_getpgrp() === posix_getpid();
echo $leader ? "Уже лидер группы: прямой setsid обычно откажет\n" : "Не лидер группы\n";
Ожидаемый результат
Одна из двух строк.

Это объясняет ограничение setsid; между проверкой и действием всё равно требуется обработать системный отказ. Новая session не равна созданию дочернего процесса. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpgid, posix_setpgid, posix_setsid.

posix_getpgidПолучить PGID заданного процесса для диагностики собственного дерева worker.

PHP4+ · posix (Unix)

posix_getpgid(int $process_id): int|false

Получить PGID заданного процесса для диагностики собственного дерева worker.

Часть вызоваОбъяснение
Сигнатураposix_getpgid(int $process_id): int|false
ВходPID; 0 означает текущий процесс.
Результат и отказPGID как int либо false при отказе/исчезнувшем PID.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Функция условно компилируется на поддерживающих её ОС. Результат относится к моменту вызова: это не резервирование PID и не разрешение посылать сигнал.

Группа текущего процесса через аргумент0Пример для указанного окружения
<?php
declare(strict_types=1);

$group = posix_getpgid(0);
if ($group === false) throw new RuntimeException('PGID недоступен');
echo 'PGID=', $group, "\n";
Ожидаемый результат
PGID=N.

0 здесь служебное значение «я», а не несуществующий процесс. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Сравнить свою группу и группу текущего родителяПример для указанного окружения
<?php
declare(strict_types=1);

$parent = posix_getppid();
if ($parent <= 0) throw new RuntimeException('Родитель не виден в этом namespace');
$parentGroup = posix_getpgid($parent);
if ($parentGroup === false) {
    echo "Родитель уже завершился или недоступен\n";
} else {
    echo $parentGroup === posix_getpgrp() ? "Общая группа процессов\n" : "Разные группы\n";
}
Ожидаемый результат
Общая/разные группы либо сообщение об отказе.

Не подставляем PPID0: для getpgid0 это был бы текущий процесс, и отчёт ложно описал бы родителя. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpgrp, posix_getppid, posix_setpgid.

posix_getsidПосмотреть принадлежность процесса к Unix сеансу, например после запуска через менеджер служб.

PHP4+ · posix (Unix)

posix_getsid(int $process_id): int|false

Посмотреть принадлежность процесса к Unix сеансу, например после запуска через менеджер служб.

Часть вызоваОбъяснение
Сигнатураposix_getsid(int $process_id): int|false
ВходPID; 0 — свой процесс.
Результат и отказSID (PGID лидера сеанса) либо false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это не session_id браузера и не PHP $_SESSION. В tagged8.5 PID должен быть неотрицательным и помещаться в диапазон pid_t: вне его ValueError. Доступ к чужим сеансам зависит от ОС.

Прочитать собственный SIDПример для указанного окружения
<?php
declare(strict_types=1);

$sid = posix_getsid(0);
echo $sid === false ? "SID недоступен\n" : "SID=$sid\n";
Ожидаемый результат
SID=N либо сообщение об отказе.

Сеанс объединяет группы процессов; он не содержит заказы/корзину посетителя. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Различить группу и сеансПример для указанного окружения
<?php
declare(strict_types=1);

$sid = posix_getsid(posix_getpid());
if ($sid === false) throw new RuntimeException('Не прочитан SID');
echo 'PID=', posix_getpid(), '; PGID=', posix_getpgrp(), '; SID=', $sid, "\n";
Ожидаемый результат
Три подписанных идентификатора.

Несколько PGID могут принадлежать одному SID. Используйте эти метки при разборе терминального job control, а не как средство авторизации. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpgid, posix_setsid.

posix_setpgidВыделить собственный одноразовый job в группу процессов для дальнейшего управляемого жизненного цикла.

PHP4+ · posix (Unix)

posix_setpgid(int $process_id, int $process_group_id): bool

Выделить собственный одноразовый job в группу процессов для дальнейшего управляемого жизненного цикла.

Часть вызоваОбъяснение
Сигнатураposix_setpgid(int $process_id, int $process_group_id): bool
Входprocess_id0 — текущий процесс; process_group_id0 — использовать PID выбранного процесса как PGID.
Результат и отказtrue либо false; с PHP8.5 отрицательные/слишком большие аргументы вызывают ValueError.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Можно менять себя или допустимого собственного ребёнка в рамках сеанса; нельзя произвольно перетасовать чужие процессы или session leader. Ограничения exec и гонки запуска требуют обработки отказа.

Создать группу для собственного отдельного CLI процессаПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен одноразовый CLI');
if (!posix_setpgid(0, 0)) throw new RuntimeException('ОС не разрешила новую группу');
echo 'PGID=', posix_getpgrp(), '; PID=', posix_getpid(), "\n";
Ожидаемый результат
При успехе PGID совпадает с PID; возможен отказ, например для session leader.

Пример заканчивается сразу, не посылает сигналы группе и не меняет родительскую shell. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Выявить неверное отрицательное значение до системного вызоваПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_VERSION_ID < 80500) throw new RuntimeException('Урок ошибки рассчитан на PHP8.5');
try {
    posix_setpgid(-1, 0);
} catch (ValueError $error) {
    echo "Отрицательный PID не принимается setpgid\n";
}
Ожидаемый результат
Отрицательный PID не принимается setpgid.

У kill отрицательный PID имеет отдельный смысл, а у setpgid недопустим. Нельзя переносить значения между функциями по созвучию. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpgrp, posix_getpgid, posix_setsid.

posix_setsidСоздать новый Unix сеанс в специально выделенном дочернем CLI процессе.

PHP4+ · posix (Unix)

posix_setsid(): int

Создать новый Unix сеанс в специально выделенном дочернем CLI процессе.

Часть вызоваОбъяснение
Сигнатураposix_setsid(): int
ВходНет.
Результат и отказНовый SID как int; при ошибке именно -1, не false.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

setsid не создаёт ребёнка, не запускает daemon полностью, не перенаправляет stdin/out/err и не меняет каталог. Лидер группы не может вызвать его успешно. В PHP8.5 wrapper возвращает setsid напрямую и не обновляет сохранённый posix_last_error; не приписывайте отказу старое сообщение.

Правильно сравнить отрицательный результатПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен одноразовый CLI');
$sid = posix_setsid();
echo $sid === -1 ? "Новый сеанс не создан\n" : "Создан SID=$sid\n";
Ожидаемый результат
SID=N либо Новый сеанс не создан.

Проверка if (!$sid) ошибочна: -1 — truthy. Не меняйте сеанс длительно живущего рабочего процесса сайта. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Понятный сценарий с собственным коротким ребёнкомПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || !function_exists('pcntl_fork')) throw new RuntimeException('Нужны Unix CLI, PCNTL и POSIX');
$child = pcntl_fork();
if ($child === -1) throw new RuntimeException('fork не выполнен');
if ($child === 0) {
    $sid = posix_setsid();
    echo $sid === -1 ? "Не создан сеанс ребёнка\n" : "Ребёнок создал новый сеанс\n";
    exit($sid === -1 ? 1 : 0);
}
if (pcntl_waitpid($child, $status) !== $child) throw new RuntimeException('Ожидание ребёнка не выполнено');
echo "Родитель дождался собственного ребёнка\n";
Ожидаемый результат
Строка ребёнка о результате setsid, затем строка родителя.

Ребёнок наследует PGID родителя, но получает другой PID и обычно уже не лидер группы. Он сразу завершается; waitpid не оставляет zombie. Для production supervisor обычно запускает foreground worker сам. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getsid, posix_getpid, posix_getpgrp.

posix_killПередать сигнал собственному управляемому worker или проверить возможность отправки без фактического сигнала.

PHP4+ · posix (Unix)

posix_kill(int $process_id, int $signal): bool

Передать сигнал собственному управляемому worker или проверить возможность отправки без фактического сигнала.

Часть вызоваОбъяснение
Сигнатураposix_kill(int $process_id, int $signal): bool
ВходPID>0 — процесс; 0 — своя process group; -1 — широкий набор разрешённых процессов ОС; PID<-1 — группа abs(PID). signal0 ничего не отправляет. Именованные сигналы поставляет PCNTL.
Результат и отказtrue — запрос принят; false — например недостаточно прав/нет цели/неверный сигнал. Это не подтверждение выполнения обработчика или завершения процесса. PHP8.5 ValueError при PID вне диапазона платформы.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

signal0 — не health-check и не надёжный lock. Отказ может означать EPERM, а не отсутствие; PID может быть переиспользован сразу после проверки. Не посылайте сигнал PID из пользовательской формы или старого файла без собственной модели владения. SIGKILL нельзя перехватить; SIGTERM допускает обработку.

Проверить свой PID без отправки сигналаПример для указанного окружения
<?php
declare(strict_types=1);

$pid = posix_getpid();
echo posix_kill($pid, 0) ? "Сигнал своему PID разрешён\n" : "Проверка не удалась\n";
Ожидаемый результат
Одна строка результата проверки.

В отличие от названия kill вызов с0 никого не завершает. Даже успешная проверка не гарантирует, что бизнес-задача продвигается. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Показать доставку сигнала самому себе с обработчикомПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli' || !function_exists('pcntl_signal')) throw new RuntimeException('Нужны CLI и PCNTL');
$received = false;
pcntl_async_signals(true);
if (!pcntl_signal(SIGUSR1, function () use (&$received) { $received = true; })) {
    throw new RuntimeException('Обработчик не установлен');
}
if (!posix_kill(posix_getpid(), SIGUSR1)) throw new RuntimeException('Сигнал не отправлен');
pcntl_signal_dispatch();
echo $received ? "Обработчик получил уведомление\n" : "Доставка ещё не подтверждена\n";
Ожидаемый результат
При обработанном сигнале — Обработчик получил уведомление.

Обработчик установлен до отправки и только меняет флаг. Это демонстрация уведомления, не передача JSON/заказа: для данных используют канал, socket или очередь. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getpid, posix_get_last_error, posix_strerror, posix_getpgrp.

posix_accessДиагностировать доступ к файлу с реальными UID/GID процесса, например при разборе привилегированного launcher.

PHP4+ · posix (Unix)

posix_access(string $filename, int $flags = 0): bool

Диагностировать доступ к файлу с реальными UID/GID процесса, например при разборе привилегированного launcher.

Часть вызоваОбъяснение
Сигнатураposix_access(string $filename, int $flags = 0): bool
ВходПуть; flags0 равен POSIX_F_OK, остальные маски можно объединять.
Результат и отказtrue — проверка прошла; false — отказ/нет пути/ограничение open_basedir; errno помогает диагностике.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Проверка real IDs может отличаться от последующего fopen, который использует effective права. Между проверкой и действием путь может измениться (TOCTOU). Не строят безопасное открытие по принципу «access вернулtrue, значит ошибка невозможна».

Флаги POSIX_F_OK/R_OK/W_OK/X_OK: существование, чтение, запись, выполнение/поиск в каталоге. Побитовое | объединяет требования. На каталогах X означает проход по пути, R — чтение списка имён, W обычно нужен для изменения записей вместе с X. Проверяется путь с учётом идентичности, а не только числовые биты chmod.

Проверить свой файл каталогаПример для указанного окружения
<?php
declare(strict_types=1);

$path = __DIR__ . '/catalog.txt';
echo posix_access($path, POSIX_R_OK) ? "Real UID может читать файл\n" : "Чтение не подтверждено\n";
Ожидаемый результат
Для доступной fixture — Real UID может читать файл.

filename передан строкой; R_OK просит чтение. Возвращается bool, а не содержимое файла. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Проверить чтение и проход каталога как диагностикуПример для указанного окружения
<?php
declare(strict_types=1);

$flags = POSIX_R_OK | POSIX_X_OK;
if (!posix_access(__DIR__, $flags)) {
    $code = posix_get_last_error();
    echo 'Каталог недоступен real IDs: ', $code, ' ', posix_strerror($code), "\n";
} else {
    echo "Real IDs разрешают список и проход\n";
}
Ожидаемый результат
Сообщение об успешной диагностике либо код и текст отказа.

Не используем logical || вместо битового |: иначе два флага превратятся в bool. X у каталога не означает «выполнить каталог». Потенциально меняющийся путь всё равно проверяют в самой операции. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_eaccess, posix_getuid, posix_get_last_error.

posix_eaccessПроверить доступ с действующими effective UID/GID, когда выясняем права работающего worker.

PHP8.3+ · posix (Unix)

posix_eaccess(string $filename, int $flags = 0): bool

Проверить доступ с действующими effective UID/GID, когда выясняем права работающего worker.

Часть вызоваОбъяснение
Сигнатураposix_eaccess(string $filename, int $flags = 0): bool
ВходПуть и та же маска F_OK/R_OK/W_OK/X_OK.
Результат и отказbool; ошибка ОС — false; в tagged8.5 пустой неразрешимый путь вызывает ValueError. Доступно с8.3 при поддержке eaccess.
Среда и версияPHP8.3+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это удобная диагностика, но не замена обработке fopen/fwrite. Политики ACL, mount, capabilities, open_basedir и изменения пути влияют на результат.

Флаги POSIX_F_OK/R_OK/W_OK/X_OK: существование, чтение, запись, выполнение/поиск в каталоге. Побитовое | объединяет требования. На каталогах X означает проход по пути, R — чтение списка имён, W обычно нужен для изменения записей вместе с X. Проверяется путь с учётом идентичности, а не только числовые биты chmod.

Проверить effective чтениеПример для указанного окружения
<?php
declare(strict_types=1);

if (!function_exists('posix_eaccess')) throw new RuntimeException('Нужна поддержка eaccess и PHP8.3+');
echo posix_eaccess(__DIR__ . '/catalog.txt', POSIX_R_OK)
    ? "Effective IDs могут читать каталог товаров\n" : "Чтение не подтверждено\n";
Ожидаемый результат
Для доступного файла — строка об effective чтении.

Вход — путь к данным, выход — только ответ на проверку доступа. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Сравнить real и effective доступ к одному файлуПример для указанного окружения
<?php
declare(strict_types=1);

$path = __DIR__ . '/catalog.txt';
echo 'Real: ', posix_access($path, POSIX_R_OK) ? 'да' : 'нет', "\n";
echo 'Effective: ', posix_eaccess($path, POSIX_R_OK) ? 'да' : 'нет', "\n";
Ожидаемый результат
Две строки; обычный запуск обычно даёт одинаковый ответ.

Различие возможно в специальном launcher с разными IDs. Проверки не читают файл и не подтверждают целостность его содержимого. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_access, posix_geteuid, posix_getegid.

posix_getcwdПонять, почему относительный путь cron job указывает не туда, куда ожидал разработчик.

PHP4+ · posix (Unix)

posix_getcwd(): string|false

Понять, почему относительный путь cron job указывает не туда, куда ожидал разработчик.

Часть вызоваОбъяснение
Сигнатураposix_getcwd(): string|false
ВходНет.
Результат и отказАбсолютный текущий рабочий каталог или false с POSIX errno.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Рабочий каталог меняется через chdir и может отличаться от __DIR__ файла. Отказ возможен после удаления каталога или из-за отсутствия права поиска по пути. Для переносимого кода есть обычный getcwd.

Вывести две разные точки отсчётаПример для указанного окружения
<?php
declare(strict_types=1);

$working = posix_getcwd();
if ($working === false) throw new RuntimeException('Рабочий каталог не определён');
echo 'CWD: ', $working, "\n";
echo 'Каталог скрипта: ', __DIR__, "\n";
Ожидаемый результат
Два абсолютных пути, которые не обязаны совпасть.

Открытие catalog.txt ищет относительно CWD, а __DIR__ . /catalog.txt — рядом с данным исходником. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Временно сменить каталог и вернуть его в finallyПример для указанного окружения
<?php
declare(strict_types=1);

$before = posix_getcwd();
if ($before === false) throw new RuntimeException('Не определён CWD');
try {
    if (!chdir(__DIR__)) throw new RuntimeException('chdir не выполнен');
    echo 'Читаем относительно: ', posix_getcwd(), "\n";
} finally {
    if (!chdir($before)) throw new RuntimeException('Не восстановлен CWD');
}
echo "Рабочий каталог восстановлен\n";
Ожидаемый результат
Путь скрипта, затем строка о восстановлении.

В библиотеке изменение CWD влияет на другой код процесса; абсолютные пути часто избавляют от этой скрытой зависимости. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_access, posix_get_last_error.

posix_mkfifoСоздать именованный канал для обмена байтами между своими локальными процессами.

PHP4+ · posix (Unix)

posix_mkfifo(string $filename, int $permissions): bool

Создать именованный канал для обмена байтами между своими локальными процессами.

Часть вызоваОбъяснение
Сигнатураposix_mkfifo(string $filename, int $permissions): bool
ВходНовый путь; права, например 0600 в восьмеричной записи. Итоговый режим: permissions & ~umask.
Результат и отказtrue если узел FIFO создан, иначе false. Чтение/запись идут затем обычными stream функциями.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

FIFO — байтовый канал, не обычный файл хранения и не очередь с подтверждением. Открытие одного конца может блокироваться до второго; EOF/частичные чтения/записи требуют протокола. Для двустороннего разговора переносимее два FIFO либо Unix socket, а не обещание портативного r+.

Создать собственный FIFO и удалить узелПример для указанного окружения
<?php
declare(strict_types=1);

$dir = sys_get_temp_dir() . '/php-fifo-' . bin2hex(random_bytes(8));
if (!mkdir($dir, 0700)) throw new RuntimeException('Каталог не создан');
$path = $dir . '/events';
try {
    if (!posix_mkfifo($path, 0600)) throw new RuntimeException('FIFO не создан');
    echo filetype($path), "\n";
} finally {
    if (file_exists($path)) unlink($path);
    rmdir($dir);
}
Ожидаемый результат
fifo

Только собственный случайный каталог; не открываем канал, поэтому не ждём второго процесса. После удаления имени уже открытые дескрипторы у других участников жили бы по правилам ОС. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Увидеть влияние umask на доступ к каналуПример для указанного окружения
<?php
declare(strict_types=1);

$dir = sys_get_temp_dir() . '/php-fifo-mode-' . bin2hex(random_bytes(8));
if (!mkdir($dir, 0700)) throw new RuntimeException('Каталог не создан');
$path = $dir . '/events';
$oldMask = umask(0077);
try {
    if (!posix_mkfifo($path, 0666)) throw new RuntimeException('FIFO не создан');
    clearstatcache(true, $path);
    printf("Режим: %04o\n", fileperms($path) & 0777);
} finally {
    umask($oldMask);
    if (file_exists($path)) unlink($path);
    rmdir($dir);
}
Ожидаемый результат
Режим: 0600

0666 & ~0077 оставляет чтение/запись владельцу. Десятичное666 — другое число. umask меняет окружение процесса и здесь восстановлен; это не готовый многопоточный шаблон. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_mknod, posix_fpathconf.

posix_mknodСоздать специальный файловый узел, когда системная интеграция действительно требует типа FIFO/устройства.

PHP5.1+ · posix (Unix)

posix_mknod(string $filename, int $flags, int $major = 0, int $minor = 0): bool

Создать специальный файловый узел, когда системная интеграция действительно требует типа FIFO/устройства.

Часть вызоваОбъяснение
Сигнатураposix_mknod(string $filename, int $flags, int $major = 0, int $minor = 0): bool
ВходНовый путь; flags = один POSIX_S_IF* | права. major/minor — номера устройства для CHR/BLK, не длина файла.
Результат и отказtrue либо false; в PHP8.5 major0 для CHR/BLK вызывает ValueError. Доступность типов/создания зависит от ОС и прав.
Среда и версияPHP5.1+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Обычный сайт не создаёт device nodes. Для обычного файла проще fopen с x; для FIFO понятнее mkfifo; socket endpoint создают socket_bind. Не копируем учебные примеры с world-writable устройствами. Указание S_IFSOCK не создаёт слушающий socket.

Показать тип и права на безопасном узле FIFOПример для указанного окружения
<?php
declare(strict_types=1);

$dir = sys_get_temp_dir() . '/php-node-' . bin2hex(random_bytes(8));
if (!mkdir($dir, 0700)) throw new RuntimeException('Каталог не создан');
$path = $dir . '/events';
try {
    if (!posix_mknod($path, POSIX_S_IFIFO | 0600)) throw new RuntimeException('ОС отклонила mknod');
    echo filetype($path), "\n";
} finally {
    if (file_exists($path)) unlink($path);
    rmdir($dir);
}
Ожидаемый результат
fifo на разрешающей это ОС либо исключение; устройство не создаётся.

Битовая маска описывает одновременно тип и доступ; major/minor здесь не используются. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Сравнить создание обычного пустого узла с записью данныхПример для указанного окружения
<?php
declare(strict_types=1);

$dir = sys_get_temp_dir() . '/php-node-file-' . bin2hex(random_bytes(8));
if (!mkdir($dir, 0700)) throw new RuntimeException('Каталог не создан');
$path = $dir . '/report';
try {
    if (!posix_mknod($path, POSIX_S_IFREG | 0600)) throw new RuntimeException('Узел не создан');
    echo filetype($path), ': ', filesize($path), "\n";
} finally {
    if (file_exists($path)) unlink($path);
    rmdir($dir);
}
Ожидаемый результат
file: 0 на поддерживающей ОС.

mknod создаёт узел, но не открывает stream и не записывает отчёт. В прикладном коде fopen($path, "x") объединяет создание с получением дескриптора. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_mkfifo, posix_access.

posix_isattyВыбрать формат CLI отчёта: удобный для человека в терминале или чистый текст при перенаправлении в файл.

PHP4+ · posix (Unix)

posix_isatty(resource|int $file_descriptor): bool

Выбрать формат CLI отчёта: удобный для человека в терминале или чистый текст при перенаправлении в файл.

Часть вызоваОбъяснение
Сигнатураposix_isatty(resource|int $file_descriptor): bool
ВходОткрытый stream resource либо настоящий числовой fd.
Результат и отказtrue для терминала; false для обычного файла/pipe/невалидного fd. PHP8.5 предупреждает о недопустимом диапазоне; errno для плохого fd уточнён в8.4.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

false — часто нормальный результат перенаправления, не авария. TTY не обещает поддержку цвета/UTF-8. Для PHP stream часто достаточно stream_isatty без расширения POSIX.

ОС дескриптор — малое целое, например0/1/2 для stdin/stdout/stderr при обычном CLI запуске. PHP stream resource — другая сущность: передавайте сам STDOUT/$stream, не (int)$stream. Числовой ID PHP resource не обязан быть OS fd. Не каждый wrapper предоставляет настоящий дескриптор.

Определить назначение STDOUTПример для указанного окружения
<?php
declare(strict_types=1);

echo posix_isatty(STDOUT) ? "Отчёт идёт в терминал\n" : "Отчёт идёт в файл или канал\n";
Ожидаемый результат
Результат зависит от перенаправления вывода.

php report.php и php report.php > report.txt дадут разные ветки без изменения кода. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Оставить экспорт машинно читаемымПример для указанного окружения
<?php
declare(strict_types=1);

$interactive = posix_isatty(STDOUT);
$items = [['sku' => 'A42', 'stock' => 7]];
if ($interactive) echo "Остатки каталога\n";
foreach ($items as $item) echo $item['sku'], ';', $item['stock'], "\n";
Ожидаемый результат
В терминале заголовок и A42;7; в pipe/файле только A42;7.

Не добавляем progress bar и управляющие коды к данным, которые получает следующая программа. Для общего CSV с кавычками используйте fputcsv. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_ttyname, posix_ctermid.

posix_ttynameУзнать конкретное терминальное устройство открытого потока при диагностике CLI.

PHP4+ · posix (Unix)

posix_ttyname(resource|int $file_descriptor): string|false

Узнать конкретное терминальное устройство открытого потока при диагностике CLI.

Часть вызоваОбъяснение
Сигнатураposix_ttyname(resource|int $file_descriptor): string|false
ВходStream или OS fd.
Результат и отказАбсолютный путь терминала либо false. Неверные integer fd дают warning с8.3; с8.5 stored errno устанавливается EBADF.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Путь может быть /dev/pts/N, но не надо конструировать его вручную. Возвращённая строка не открывает устройство и не обещает, что оно останется тем же.

ОС дескриптор — малое целое, например0/1/2 для stdin/stdout/stderr при обычном CLI запуске. PHP stream resource — другая сущность: передавайте сам STDOUT/$stream, не (int)$stream. Числовой ID PHP resource не обязан быть OS fd. Не каждый wrapper предоставляет настоящий дескриптор.

Подписать свой stdoutПример для указанного окружения
<?php
declare(strict_types=1);

$terminal = posix_ttyname(STDOUT);
echo $terminal === false ? "STDOUT не имеет имени терминала\n" : "Терминал: $terminal\n";
Ожидаемый результат
Путь терминала либо сообщение о его отсутствии.

При перенаправлении вывода отсутствие terminal name нормально. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Различить терминал ввода и перенаправленный выводПример для указанного окружения
<?php
declare(strict_types=1);

foreach (['stdin' => STDIN, 'stdout' => STDOUT] as $name => $stream) {
    if (!posix_isatty($stream)) {
        echo "$name: не терминал\n";
        continue;
    }
    $terminal = posix_ttyname($stream);
    echo $name, ': ', $terminal === false ? 'имя недоступно' : $terminal, "\n";
}
Ожидаемый результат
Две строки о stdin/stdout; один может быть терминалом, другой — файлом.

Например CLI утилита может читать клавиатуру, а результат отправлять в файл. Проверяем каждый поток отдельно. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_isatty, posix_ctermid.

posix_ctermidПолучить системный путь к управляющему терминалу процесса, отличая его от конкретного устройства STDOUT.

PHP4+ · posix (Unix)

posix_ctermid(): string|false

Получить системный путь к управляющему терминалу процесса, отличая его от конкретного устройства STDOUT.

Часть вызоваОбъяснение
Сигнатураposix_ctermid(): string|false
ВходНет.
Результат и отказПуть строкой либо false; возможна пустая строка по поведению libc, её также обрабатываем.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

На Linux часто получается /dev/tty — общее имя обращения к своему controlling terminal. Наличие строки не доказывает, что процесс имеет терминал: cron может не иметь его и открытие пути откажет. Не сравнивайте строку с ttyname как уникальный ID.

Прочитать имя без открытия устройстваПример для указанного окружения
<?php
declare(strict_types=1);

$path = posix_ctermid();
echo $path === false || $path === '' ? "Путь не получен\n" : "Controlling terminal path: $path\n";
Ожидаемый результат
Путь вроде /dev/tty либо сообщение об отсутствии.

Никакого чтения клавиатуры не происходит; программа только получает имя. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Показать разницу общего пути и stdoutПример для указанного окружения
<?php
declare(strict_types=1);

$controlling = posix_ctermid();
$output = posix_ttyname(STDOUT);
echo 'Controlling path: ', $controlling === false || $controlling === '' ? '(нет)' : $controlling, "\n";
echo 'STDOUT device: ', $output === false ? '(не терминал)' : $output, "\n";
Ожидаемый результат
Две строки; при перенаправлении stdout его terminal name может отсутствовать, хотя общий путь ctermid есть.

Так объясняется, почему нельзя решать интерактивность только по ctermid; для конкретного потока используйте isatty. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_ttyname, posix_isatty, posix_setsid.

posix_unameДобавить сведения о среде в локальный диагностический отчёт, когда один и тот же worker ведёт себя по-разному на двух серверах.

PHP4+ · posix (Unix)

posix_uname(): array|false

Добавить сведения о среде в локальный диагностический отчёт, когда один и тот же worker ведёт себя по-разному на двух серверах.

Часть вызоваОбъяснение
Сигнатураposix_uname(): array|false
ВходНет.
Результат и отказМассив строк sysname, nodename, release, version, machine; необязательный GNU domainname; false при отказе.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Не предполагайте формат release из трёх чисел и не используйте строку версии как единственную проверку возможностей. GNU domainname относится к NIS/YP, а не гарантированно к DNS домену сайта. Не публикуйте весь отчёт посетителям.

ПолеЧто узнаём
sysnameСемейство ОС, например Linux.
nodenameСетевое имя узла в системном контексте; контейнер может иметь своё.
releaseВыпуск ядра/ОС, формат не задан PHP.
versionДополнительная информация о сборке.
machineАппаратная архитектура в представлении ОС.
domainnameНеобязательное GNU расширение; не адрес веб-сайта.
Прочитать только нужную информациюПример для указанного окружения
<?php
declare(strict_types=1);

$system = posix_uname();
if ($system === false) throw new RuntimeException('Данные ОС недоступны');
echo $system['sysname'], ' / ', $system['machine'], "\n";
Ожидаемый результат
Например Linux / x86_64; точные строки задаёт ОС.

Возвращается массив: квадратные скобки выбирают конкретное поле. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Аккуратно составить локальный отчётПример для указанного окружения
<?php
declare(strict_types=1);

$system = posix_uname();
if ($system === false) throw new RuntimeException('uname не выполнен');
$report = ['os' => $system['sysname'], 'release' => $system['release'], 'php' => PHP_VERSION];
$report['nis_domain'] = $system['domainname'] ?? '(поле отсутствует)';
echo json_encode($report, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES), "\n";
Ожидаемый результат
JSON с ОС, выпуском, PHP и NIS полем/маркером отсутствия.

?? предотвращает предположение, что GNU поле есть в каждой сборке. Для реальной возможности проверяйте нужную функцию/константу. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_sysconf.

posix_timesОтделить потраченное процессором время обработки каталога от времени ожидания сети или диска.

PHP4+ · posix (Unix)

posix_times(): array|false

Отделить потраченное процессором время обработки каталога от времени ожидания сети или диска.

Часть вызоваОбъяснение
Сигнатураposix_times(): array|false
ВходНет.
Результат и отказМассив целых clock ticks: ticks, utime, stime, cutime, cstime; false при системном отказе.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это не наносекунды и не готовые секунды. cutime/cstime в системном times — накопленное CPU время завершённых и подождённых детей, а не сумма текущего процесса с детьми. ticks имеет платформенную точку отсчёта; не выдавайте его за переносимый uptime. Возможны переполнения/отрицательные значения.

ПолеСмысл
utimeCPU время своего процесса в пользовательском режиме.
stimeCPU время ядра от имени своего процесса.
cutime/cstimeУчтённое время детей после соответствующего ожидания; не текущий родитель ещё раз.
ticksСистемный счётчик times с платформенной эпохой. Для интервалов реального времени используйте hrtime.
Посмотреть именно счётчики CPUПример для указанного окружения
<?php
declare(strict_types=1);

$times = posix_times();
if ($times === false) throw new RuntimeException('CPU счётчики недоступны');
echo 'User ticks: ', $times['utime'], '; system ticks: ', $times['stime'], "\n";
Ожидаемый результат
Два числовых счётчика, в коротком процессе могут быть0.

Маленькая задача может быть короче одного системного тика, и ноль не означает, что код не исполнялся. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Измерить CPU участка с переводом тиков в секундыПример для указанного окружения
<?php
declare(strict_types=1);

if (!defined('POSIX_SC_CLK_TCK')) throw new RuntimeException('Нужна поддержка POSIX_SC_CLK_TCK, PHP8.4+');
$hz = posix_sysconf(POSIX_SC_CLK_TCK);
$before = posix_times();
if ($hz <= 0 || $before === false) throw new RuntimeException('Нет корректных счётчиков');
$digest = '';
for ($i = 0; $i < 10000; $i++) $digest = hash('sha256', 'catalog-' . $i);
$after = posix_times();
if ($after === false) throw new RuntimeException('Не прочитан итог');
$ticks = ($after['utime'] - $before['utime']) + ($after['stime'] - $before['stime']);
if ($ticks < 0) throw new RuntimeException('Счётчик переполнился или изменился');
printf("CPU seconds: %.6f\n", $ticks / $hz);
Ожидаемый результат
Неотрицательное измерение CPU секунд, возможно0 на быстрой машине.

Не зашиваем100 ticks/s; узнаём частоту ОС. Это одно измерение конкретного участка, не универсальный рейтинг быстродействия PHP. Для latency API нужны отдельные wall-clock интервалы. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_sysconf, posix_getrlimit.

posix_getrlimitПонять отказ открытия новых файлов или запуска задач до того, как увеличивать PHP memory_limit наугад.

PHP4+ · posix (Unix)

posix_getrlimit(?int $resource = null): array|false

Понять отказ открытия новых файлов или запуска задач до того, как увеличивать PHP memory_limit наугад.

Часть вызоваОбъяснение
Сигнатураposix_getrlimit(?int $resource = null): array|false
Входnull/без аргумента — набор именованных лимитов; с PHP8.3 можно передать POSIX_RLIMIT_* для одного ресурса.
Результат и отказОбщий набор содержит ключи soft X/hard X. Один ресурс в tagged PHP8.5 возвращает [0 => soft, 1 => hard]. Значения int или строка "unlimited"; false при отказе.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Soft — действующая граница; hard — потолок, до которого обычный процесс может поднять soft. Снижение hard для обычного процесса необратимо. Набор без аргумента ограничен таблицей wrapper, не обязательно включает все доступные RLIMIT_*; отдельный ресурс запросите явно.

Имена общего массива: core, data, stack, virtualmem, totalmem, rss, maxproc, memlock, cpu, filesize, openfiles, а на соответствующих системах kqueues/npts. Есть только поддерживаемые ключи. filesize — размер файла, не data segment; cpu — CPU секунды; openfiles — граница дескрипторов. Полная таблица единиц и ресурсов отделяет память процесса от PHP memory_limit.

Прочитать лимит открытых дескрипторов без измененияПример для указанного окружения
<?php
declare(strict_types=1);

$limits = posix_getrlimit();
if ($limits === false) throw new RuntimeException('Лимиты недоступны');
echo 'Soft openfiles: ', $limits['soft openfiles'] ?? '(нет ключа)', "\n";
echo 'Hard openfiles: ', $limits['hard openfiles'] ?? '(нет ключа)', "\n";
Ожидаемый результат
Два лимита или маркеры отсутствующего ключа.

Служба наследует лимиты launcher/supervisor; значения интерактивной shell могут быть другими. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Правильно разобрать форму одного ресурсаПример для указанного окружения
<?php
declare(strict_types=1);

$limits = posix_getrlimit(POSIX_RLIMIT_NOFILE);
if ($limits === false) throw new RuntimeException('NOFILE недоступен');
[$soft, $hard] = $limits;
echo 'Soft=', $soft, '; hard=', $hard, "\n";
if (is_int($soft) && $soft < 128) echo "Мало дескрипторов для проекта с большим числом соединений\n";
Ожидаемый результат
Soft/hard и дополнительное сообщение для числового soft<128.

Строку unlimited не преобразуем в0. Выбор128 — политика учебного проекта, а не универсальный минимум для PHP. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_setrlimit, posix_sysconf.

posix_setrlimitОграничить конкретный одноразовый обработчик системным ресурсом, не меняя общую конфигурацию всех процессов.

PHP7+ · posix (Unix)

posix_setrlimit(int $resource, int $soft_limit, int $hard_limit): bool

Ограничить конкретный одноразовый обработчик системным ресурсом, не меняя общую конфигурацию всех процессов.

Часть вызоваОбъяснение
Сигнатураposix_setrlimit(int $resource, int $soft_limit, int $hard_limit): bool
ВходРесурс POSIX_RLIMIT_*; soft/hard в единицах именно ресурса, либо POSIX_RLIMIT_INFINITY.
Результат и отказtrue или false при отказе ОС. PHP8.5 ValueError при значении ниже-1 и обычном finite soft>hard; несовместимость infinity и конечного hard тоже обрабатывайте как отказ.
Среда и версияPHP7+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Не переносите строку "unlimited" из getrlimit в int аргумент: используйте символическую константу. Не снижайте hard без намерения; обычно оставляйте существующий hard. Лимиты наследуют дети. CPU limit не заменяет сетевой timeout; память ОС отличается от memory_limit.

Отключить core dump только у своего одноразового CLIПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') throw new RuntimeException('Нужен отдельный CLI');
$limits = posix_getrlimit(POSIX_RLIMIT_CORE);
if ($limits === false) throw new RuntimeException('Не прочитан CORE');
$hard = $limits[1] === 'unlimited' ? POSIX_RLIMIT_INFINITY : $limits[1];
if (!posix_setrlimit(POSIX_RLIMIT_CORE, 0, $hard)) throw new RuntimeException('Лимит не принят');
echo "Soft CORE=0, hard сохранён\n";
Ожидаемый результат
Soft CORE=0, hard сохранён.

Изменяем soft в разрешённых пределах. Это не включает шифрование секретов и не отменяет все внешние механизмы сборщика crash dumps; показываем именно RLIMIT_CORE. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Отделить ошибку параметра от отказа ОСПример для указанного окружения
<?php
declare(strict_types=1);

if (PHP_VERSION_ID < 80500) throw new RuntimeException('Урок рассчитан на PHP8.5');
try {
    posix_setrlimit(POSIX_RLIMIT_CORE, -2, 0);
} catch (ValueError $error) {
    echo "Значение -2 не является корректным лимитом\n";
}
Ожидаемый результат
Значение -2 не является корректным лимитом.

Этот неверный аргумент отвергается до изменения лимита. Для безграничного значения есть POSIX_RLIMIT_INFINITY, не произвольное отрицательное число. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_getrlimit, posix_get_last_error.

posix_sysconfУзнать параметры ОС, нужные для расчёта размеров и настройки числа фоновых обработчиков.

PHP8.3+ · posix (Unix)

posix_sysconf(int $conf_id): int

Узнать параметры ОС, нужные для расчёта размеров и настройки числа фоновых обработчиков.

Часть вызоваОбъяснение
Сигнатураposix_sysconf(int $conf_id): int
ВходОдна POSIX_SC_* константа из полной таблицы.
Результат и отказЧисловое значение; -1 может означать неопределённый предел, отсутствие поддержки или ошибку.
Среда и версияPHP8.3+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Wrapper PHP8.5 возвращает sysconf напрямую, не обновляя POSIX last_error. По старому errno нельзя различить эти случаи. Проверяйте допустимость значения для своей задачи и используйте явно выбранный fallback. Число online CPU не равно quota контейнера или оптимальному числу HTTP запросов.

Узнать размер страницы памяти ОСПример для указанного окружения
<?php
declare(strict_types=1);

$bytes = posix_sysconf(POSIX_SC_PAGESIZE);
if ($bytes <= 0) throw new RuntimeException('Размер страницы не определён');
echo 'Страница ОС: ', $bytes, " байт\n";
Ожидаемый результат
Например Страница ОС: 4096 байт.

Это страница памяти ядра, не HTML страница и не размер PHP массива. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Получить ориентир, затем ограничить политикой проектаПример для указанного окружения
<?php
declare(strict_types=1);

$online = posix_sysconf(POSIX_SC_NPROCESSORS_ONLN);
$configuredMaximum = 4;
$workers = $online > 0 ? min($online, $configuredMaximum) : 1;
echo 'Предварительный предел worker: ', $workers, "\n";
Ожидаемый результат
Число от1 до4.

CPU значение — только стартовый ориентир. Дополнительно учитывают container quota, RAM на задачу, лимиты API и измерение latency; автоматическое создание N процессов здесь не происходит. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_times, posix_pathconf, posix_getrlimit.

posix_pathconfПроверить предел имени файла на той файловой системе, куда сохраняется экспорт.

PHP8.3+ · posix (Unix)

posix_pathconf(string $path, int $name): int|false

Проверить предел имени файла на той файловой системе, куда сохраняется экспорт.

Часть вызоваОбъяснение
Сигнатураposix_pathconf(string $path, int $name): int|false
ВходНепустой путь; name — POSIX_PC_* селектор. Для NAME_MAX передайте каталог будущего файла.
Результат и отказЧисловой предел/признак либо false; пустой путь вызывает ValueError, open_basedir может дать warning и false.
Среда и версияPHP8.3+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

NAME_MAX — длина одного компонента в байтах. PATH_MAX — иной предел; не считайте число «символами русского текста» и не пытайтесь исправить доступ одной проверкой длины.

pathconf/fpathconf относятся к конкретному объекту/файловой системе: лимит одного mount не обязательно подходит другому. В libc значение-1 при errno0 означает неопределённый предел. Tagged PHP8.5 wrapper проверяет errno после вызова, но предварительно его не обнуляет; поэтому при -1 возможна неоднозначность со старым системным errno. Для прикладной политики и false, и отрицательное значение трактуем как «надёжного положительного лимита нет», не как нулевой разрешённый размер.

Прочитать максимум компонента имениПример для указанного окружения
<?php
declare(strict_types=1);

$limit = posix_pathconf(__DIR__, POSIX_PC_NAME_MAX);
echo is_int($limit) && $limit > 0 ? "NAME_MAX=$limit байт\n" : "Предел имени не определён\n";
Ожидаемый результат
Положительный предел в байтах либо явное неизвестное значение.

Спрашиваем каталог, а не ещё не существующий полный путь файла. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Проверить фиксированное имя экспортного файлаПример для указанного окружения
<?php
declare(strict_types=1);

$directory = __DIR__;
$name = 'catalog-2026-10.csv';
$limit = posix_pathconf($directory, POSIX_PC_NAME_MAX);
if (!is_int($limit) || $limit <= 0) throw new RuntimeException('Лимит не определён, нужна политика приложения');
if (strlen($name) > $limit) throw new RuntimeException('Имя слишком длинное');
echo "Имя помещается в предел компонента\n";
Ожидаемый результат
Имя помещается в предел компонента при достаточном положительном лимите.

Это проверка одного требования. Права, свободное место, зарезервированные имена и race при создании ещё проверяются фактическим fopen. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_fpathconf, posix_sysconf.

posix_fpathconfПрочитать системный предел через уже открытый дескриптор вместо повторного разрешения пути.

PHP8.3+ · posix (Unix)

posix_fpathconf(resource|int $file_descriptor, int $name): int|false

Прочитать системный предел через уже открытый дескриптор вместо повторного разрешения пути.

Часть вызоваОбъяснение
Сигнатураposix_fpathconf(resource|int $file_descriptor, int $name): int|false
ВходОткрытый stream/настоящий OS fd; POSIX_PC_* селектор. Нельзя подставлять integer ID PHP resource.
Результат и отказЧисловой предел/признак либо false. Невалидный resource может вызвать ValueError; PHP8.5 плохой fd сопровождает warning/EBADF.
Среда и версияPHP8.3+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Открытый дескриптор привязан к открытому объекту, даже если имя позднее изменилось. Это полезное отличие от pathconf, но не резервирование свободного места и не блокировка.

pathconf/fpathconf относятся к конкретному объекту/файловой системе: лимит одного mount не обязательно подходит другому. В libc значение-1 при errno0 означает неопределённый предел. Tagged PHP8.5 wrapper проверяет errno после вызова, но предварительно его не обнуляет; поэтому при -1 возможна неоднозначность со старым системным errno. Для прикладной политики и false, и отрицательное значение трактуем как «надёжного положительного лимита нет», не как нулевой разрешённый размер.

Прочитать ограничение по настоящему файлуПример для указанного окружения
<?php
declare(strict_types=1);

$stream = fopen(__DIR__ . '/catalog.txt', 'rb');
if ($stream === false) throw new RuntimeException('Файл не открыт');
try {
    $limit = posix_fpathconf($stream, POSIX_PC_NAME_MAX);
    echo is_int($limit) && $limit > 0 ? "NAME_MAX=$limit\n" : "Предел не определён\n";
} finally { fclose($stream); }
Ожидаемый результат
Предел NAME_MAX либо сообщение об отсутствии достоверного значения.

В функцию передан сам $stream. Закрытие в finally освобождает дескриптор независимо от результата. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Прочитать PIPE_BUF для канала stdoutПример для указанного окружения
<?php
declare(strict_types=1);

if (posix_isatty(STDOUT)) throw new RuntimeException('Запустите пример с перенаправлением в pipe');
$limit = posix_fpathconf(STDOUT, POSIX_PC_PIPE_BUF);
$record = "A42;7\n";
if (!is_int($limit) || $limit <= 0) throw new RuntimeException('PIPE_BUF не определён');
echo strlen($record) <= $limit ? "Запись укладывается в PIPE_BUF\n" : "Запись превышает PIPE_BUF\n";
Ожидаемый результат
При stdout в pipe и достаточном лимите — Запись укладывается в PIPE_BUF.

PIPE_BUF ограничивает атомарность отдельного системного write в pipe, а не общую ёмкость канала. PHP stream buffering/частичные fwrite не превращаются автоматически в гарантию одного syscall. Проверка isattyfalse сама по себе также не доказывает pipe; это явная предпосылка запуска. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_pathconf, posix_mkfifo, posix_isatty.

posix_get_last_errorСохранить номер отказа POSIX сразу после операции, чтобы журнал объяснил причину.

PHP4+ · posix (Unix)

posix_get_last_error(): int

Сохранить номер отказа POSIX сразу после операции, чтобы журнал объяснил причину.

Часть вызоваОбъяснение
Сигнатураposix_get_last_error(): int
ВходНет.
Результат и отказСохранённое целое errno; начальное0, затем последний записанный wrapper код.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Числовые значения errno зависят от ОС. Не зашивайте2/13 как универсальные ENOENT/EACCES; текст зависит от libc и локали. Код нужен диагностике, результат функции — управлению.

Сначала проверяем результат конкретной операции, только затем читаем код. Сохранённая POSIX ошибка не сбрасывается каждой успешной операцией и не обновляется каждым wrapper. В частности, sysconf, setsid и initgroups нельзя диагностировать по старому коду так, будто он точно относится к последнему вызову. Для файловых stream ошибок есть своя диагностика, не POSIX errno.

Прочитать ошибку ожидаемо отсутствующего путиПример для указанного окружения
<?php
declare(strict_types=1);

$path = __DIR__ . '/missing-' . bin2hex(random_bytes(8));
if (!posix_access($path, POSIX_F_OK)) {
    $error = posix_get_last_error();
    echo 'Отказ: ', $error, ' ', posix_strerror($error), "\n";
}
Ожидаемый результат
Строка с кодом/текстом отказа для отсутствующего пути.

Ничего не создаём и не удаляем; запоминаем errno до любой другой POSIX операции. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Не потерять причину при следующих диагностических вызовахПример для указанного окружения
<?php
declare(strict_types=1);

$path = __DIR__ . '/missing-' . bin2hex(random_bytes(8));
if (!posix_access($path, POSIX_R_OK)) {
    $captured = posix_get_last_error();
    $pid = posix_getpid();
    echo json_encode(['pid' => $pid, 'operation' => 'access', 'errno' => $captured,
        'message' => posix_strerror($captured)], JSON_THROW_ON_ERROR), "\n";
}
Ожидаемый результат
Одна JSON строка с сохранённым errno и PID.

Не включаем в публичный ответ внутренние пути/детали ОС. Следующий успех не является способом «очистить ошибку». Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_errno, posix_strerror, posix_access.

posix_errnoПрочитать тот же POSIX код ошибки под коротким историческим именем.

PHP4+ · posix (Unix)

posix_errno(): int

Прочитать тот же POSIX код ошибки под коротким историческим именем.

Часть вызоваОбъяснение
Сигнатураposix_errno(): int
ВходНет.
Результат и отказТот же результат, что posix_get_last_error; это alias.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Это не отдельная очередь ошибок, не код последнего HTTP ответа и не errno всех расширений PHP. В новом коде длинное имя часто понятнее читателю.

Сначала проверяем результат конкретной операции, только затем читаем код. Сохранённая POSIX ошибка не сбрасывается каждой успешной операцией и не обновляется каждым wrapper. В частности, sysconf, setsid и initgroups нельзя диагностировать по старому коду так, будто он точно относится к последнему вызову. Для файловых stream ошибок есть своя диагностика, не POSIX errno.

Показать эквивалентность двух имёнПример для указанного окружения
<?php
declare(strict_types=1);

posix_access(__DIR__ . '/missing-' . bin2hex(random_bytes(8)), POSIX_F_OK);
$short = posix_errno();
$long = posix_get_last_error();
echo $short === $long ? "Оба имени читают один код\n" : "Код изменился\n";
Ожидаемый результат
Оба имени читают один код.

Это чтение одного сохранённого значения, а не две независимые проверки файла. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Использовать alias только в ветке отказаПример для указанного окружения
<?php
declare(strict_types=1);

$ok = posix_access(__DIR__, POSIX_R_OK | POSIX_X_OK);
if ($ok) {
    echo "Каталог доступен\n";
} else {
    $error = posix_errno();
    echo 'Доступ не подтверждён: ', posix_strerror($error), "\n";
}
Ожидаемый результат
Сообщение об успехе либо текст отказа.

После успеха не читаем старую ошибку, чтобы не создать ложную тревогу. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_get_last_error, posix_strerror.

posix_strerrorПревратить сохранённый системный код в понятную строку локального журнала.

PHP4+ · posix (Unix)

posix_strerror(int $error_code): string

Превратить сохранённый системный код в понятную строку локального журнала.

Часть вызоваОбъяснение
Сигнатураposix_strerror(int $error_code): string
ВходЦелый errno, обычно только что сохранённый posix_get_last_error.
Результат и отказСтрока libc. Неизвестный код обычно тоже представлен строкой; точный язык/формат не фиксирован.
Среда и версияPHP4+; расширение POSIX на Unix. Наличие конкретного API проверяют function_exists, константы — defined.

Текст полезен человеку, но сравнение строк "Permission denied" — хрупкая бизнес-логика. Сам вызов не повторяет операцию и не устраняет отказ.

Увидеть, что преобразуется число, а не состояние файлаПример для указанного окружения
<?php
declare(strict_types=1);

echo posix_strerror(0), "\n";
Ожидаемый результат
Системная строка для кода0, например Success; зависит от libc/локали.

Передали0 — получили его описание. Это не проверка успешности предыдущего запроса. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Сохранить номер и текст вместеПример для указанного окружения
<?php
declare(strict_types=1);

$path = __DIR__ . '/missing-' . bin2hex(random_bytes(8));
if (posix_access($path, POSIX_F_OK) === false) {
    $number = posix_get_last_error();
    $description = posix_strerror($number);
    echo 'POSIX ', $number, ': ', $description, "\n";
}
Ожидаемый результат
Код и текст ошибки отсутствующего пути.

Число позволяет сопоставлять записи на одном стенде; человек читает описание. Для принятия решения сохраняем отдельный факт отказа access. Контекст: отдельный Unix CLI процесс с расширением POSIX; числовые ID, пути и системные сообщения зависят от стенда. Проверен PHP синтаксис, а не выполнение POSIX на Windows. Изменения прав/лимитов предназначены только для одноразового учебного процесса.

Связанные действия: posix_get_last_error, posix_errno.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.