{"record":{"id":"778a9ec9c08c86f0","repo":"walkor/workerman","slug":"can-not-save-pid-to-static-pidfile","errorCode":null,"errorMessage":"can not save pid to ${static::$pidFile}","messagePattern":"can not save pid to (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Worker.php","lineNumber":1506,"sourceCode":"        if (function_exists('posix_isatty') && posix_isatty(2)) {\n            ob_start(function (string $string) {\n                file_put_contents(static::$stdoutFile, $string, FILE_APPEND);\n            }, 1);\n        }\n    }\n\n    /**\n     * Save pid.\n     */\n    protected static function saveMasterPid(): void\n    {\n        if (DIRECTORY_SEPARATOR !== '/') {\n            return;\n        }\n\n        static::$masterPid = posix_getpid();\n        if (false === file_put_contents(static::$pidFile, static::$masterPid)) {\n            throw new RuntimeException('can not save pid to ' . static::$pidFile);\n        }\n    }\n\n    /**\n     * Get all pids of worker processes.\n     *\n     * @return array\n     */\n    protected static function getAllWorkerPids(): array\n    {\n        $pidArray = [];\n        foreach (static::$pidMap as $workerPidArray) {\n            foreach ($workerPidArray as $workerPid) {\n                $pidArray[$workerPid] = $workerPid;\n            }\n        }\n        return $pidArray;\n    }","sourceCodeStart":1488,"sourceCodeEnd":1524,"githubUrl":"https://github.com/walkor/workerman/blob/1391112a61d23020e11e7b89f17050f6cfaea431/src/Worker.php#L1488-L1524","documentation":"On startup the master process writes its PID to Worker::$pidFile (default under sys_get_temp_dir()) so stop/reload/status commands can find it. file_put_contents() returning false means the file could not be written - missing directory, permission denied, read-only filesystem, or disk full - and Workerman aborts because process management would be broken.","triggerScenarios":"Custom Worker::$pidFile = '/var/run/workerman.pid' with /var/run not writable by the runtime user; the target directory was deleted; a stale pid file owned by root while the service now runs as an unprivileged user on a read-only-ish path; disk full.","commonSituations":"Hardening a service to run as non-root without adjusting the pidFile path; switching between root and app-user starts; container images with read-only root filesystems; /tmp cleaned by tmpfiles.d while using the default path assumptions.","solutions":["Point the pid file at a writable location for the run user, e.g. Worker::$pidFile = '/var/run/myapp/workerman.pid' after creating and chown-ing that directory","Check the directory exists and the user can write: 'sudo -u appuser touch <dir>/test'","Remove a stale pid file left by a root run: 'sudo rm <pidFile>'"],"exampleFix":"// before\nWorker::$pidFile = '/var/run/workerman.pid'; // /var/run not writable by app user\nWorker::runAll(); // 'can not save pid to /var/run/workerman.pid'\n\n// after\nWorker::$pidFile = '/var/run/myapp/workerman.pid';\n// provisioned once at deploy: mkdir -p /var/run/myapp && chown appuser /var/run/myapp\nWorker::runAll();","handlingStrategy":"validation","validationCode":"$pidFile = '/var/run/myapp/workerman.pid';\n$dir = dirname($pidFile);\nif (!is_dir($dir) || !is_writable($dir)) {\n    throw new RuntimeException(\"pid directory $dir missing or not writable\");\n}\nWorker::$pidFile = $pidFile;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create and chown the pid directory in the deploy script for the exact user that runs Workerman","Clean stale pid files when switching the run user (e.g. moving from root to an app user)"],"tags":["php","workerman","pid-file","filesystem","permissions","deployment"],"backgroundTag":"file-permission-denied","analyzedSha":"1391112a61d23020e11e7b89f17050f6cfaea431","analyzedAt":"2026-08-21T02:05:46.744Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}