我的tools、service、common、oss四个项目二制文件,想在tools启动后在执行安装方法时,去启动其他三个二制文件,让他们运行起来,我现在的方法可以启动其他三个服务,但是tools的项目的进程与其他三个项目进程间有依赖关联,好像是文件句柄被监听了,结果是tools停止后再重启会报错,提示 地址已使用,如图

必须要把其他三个服务全部停止后,tools才能正常重启
代码
public function startService()
{
$rootDir = dirname(base_path(false));
echo "\n========== 开始启动服务 ==========\n";
// Linux/Unix 环境 - 关键:使用 setsid 确保完全独立
// nohup: 忽略挂起信号
// setsid: 创建新会话,脱离控制终端和进程组
// &: 后台运行
// 重定向所有标准流到 /dev/null
$commands = [
"cd {$rootDir}/oss && nohup setsid ./yifanfan-localOss.bin start -d < /dev/null > /dev/null 2>&1 &",
"sleep 2",
"cd {$rootDir}/common && nohup setsid ./yifanfan-private-common.bin start -d < /dev/null > /dev/null 2>&1 &",
"sleep 2",
"cd {$rootDir}/service && nohup setsid ./yifanfan.bin start -d < /dev/null > /dev/null 2>&1 &"
];
foreach ($commands as $index => $cmd) {
echo "\n[步骤 " . ($index + 1) . "] 执行命令:{$cmd}\n";
// 使用 exec 执行命令,非阻塞
exec($cmd, $output, $returnCode);
if ($returnCode === 0 || $returnCode === null) {
echo "命令执行成功\n";
} else {
echo "命令执行失败,返回码:{$returnCode}\n";
}
// 启动后进行检查
if (strpos($cmd, 'yifanfan-localOss.bin') !== false) {
sleep(2); // 稍微等待,让进程起来
$this->verifyProcessStarted('yifanfan-localOss');
} elseif (strpos($cmd, 'yifanfan-private-common.bin') !== false) {
sleep(2);
$this->verifyProcessStarted('yifanfan-private-common');
} elseif (strpos($cmd, 'yifanfan.bin') !== false) {
sleep(10); // 主服务可能需要更长时间
$this->verifyProcessStarted('yifanfan');
}
}
//在这里添加一个延迟,确保所有子进程完全独立
sleep(10);
echo "\n========== 服务启动完成 ==========\n";
}
/**
* 验证进程是否启动成功
* @param string $processName 进程名称
* @return bool
*/
private function verifyProcessStarted(string $processName): bool
{
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows: 使用 tasklist
$output = shell_exec("tasklist /FI \"IMAGENAME eq {$processName}.exe\" 2>&1");
if (strpos($output, $processName) !== false) {
echo "✅ 进程 {$processName} 启动成功\n";
return true;
}
} else {
// Linux: 使用 pgrep
$output = shell_exec("pgrep -f {$processName} 2>&1");
if (!empty(trim($output))) {
echo "✅ 进程 {$processName} 启动成功 (PID: " . trim($output) . ")\n";
return true;
}
}
echo "❌ 进程 {$processName} 启动失败\n";
return false;
}
想要实现的效果是tools内部启动完其他三个服务后,各自可以独立,没有关联要怎么实现?
主要是其他三个服务的进程关联了tools的文件描述符,在tools启动其他三个服务时,把文件描述符清理掉
修改后的代码: