使用 Nodejs Spawn 启动 Linux 屏幕会话

Starting Linux Screen Session with Nodejs Spawn

我目前正在开发一个 Web 管理面板系统,用于管理特定游戏的游戏服务器和 mod。我希望在面板中实现一项功能,允许您通过单击启动和停止按钮单独启动和停止服务器。

为了能够标记服务器进程及其子进程,以便我以后可以再次找到它们来杀死我正在使用 Linux 屏幕并标记它们。我正在使用 nodejs 的 spawn 命令来启动屏幕。如图所示:

  console.log(`screen -m -d -S serverscreen${server.id} wine ${(args.disableWSE === true) ? 'mb_warband_dedicated.exe' : 'WSELoaderServer.exe'} -r "Configs/${args.config}" -m "${args.module}"`);


  const program = spawn(
    'screen',
    [
      '-m', '-d',
      '-S', `serverscreen${server.id}`,
      'wine',
        (args.disableWSE === true) ? 'mb_warband_dedicated.exe' : 'WSELoaderServer.exe',
        '-r', `Configs/${args.config}`,
        '-m', `${args.module}`
    ],
    {
      cwd: currentGameserverPath,
      detached: true,
      stdio: 'ignore'
    }
  );

但是,我遇到了一个问题,我已经用尽了所有知识来尝试解决。该命令在 spawn 中使用时不起作用,即我可以 运行 console.log 中显示的命令进入 cwd 目录并且游戏服务器将愉快地启动,但是,当 spawn 命令被称为屏幕不启动。我已经记录了 stderr 和 stdout,两者都是空的,并且 spawn 以 0.

退出

有什么建议吗?

为了获得更多上下文,这里是封装此代码片段的函数的其余部分:

export default async (parent, args, context) => {
  /* Check for Permissions */
  if (context.user === null)
    throw new Error('You must be logged in to complete this action.');

  const requestingAdmin = await AdminPermission.findOne({
    server: args.serverID,
    admin: context.user
  });

  if (requestingAdmin === null)
    throw new Error('You do not have permission to do that.');

  const server = await Server.findOne({
    id: args.serverID
  });
  if(server === null) throw new Error('Server not found.');

  const currentGameserverPath = path.join(
    require.resolve('gameservers'),
    `../${server.id}`
  );
  if (!fs.existsSync(currentGameserverPath))
    throw new Error('Server folder does not exist!');


  const executablePath = path.join(
    currentGameserverPath,
    (args.disableWSE === true) ? '/mb_warband_dedicated.exe' : '/WSELoaderServer.exe'
  );
  if (!fs.existsSync(executablePath)) throw new Error('Executable does not exist!');

  const moduleFolder = path.join(currentGameserverPath, `/Modules/${args.module}`);
  if (!fs.existsSync(moduleFolder)) throw new Error('Module does not exist!');

  let configFile = path.join(currentGameserverPath, `/Configs/${args.config}`);
  if (!fs.existsSync(configFile)) throw new Error('Config does not exist!');

  console.log(`screen -m -d -S serverscreen${server.id} wine ${(args.disableWSE === true) ? 'mb_warband_dedicated.exe' : 'WSELoaderServer.exe'} -r "Configs/${args.config}" -m "${args.module}"`);


  const program = spawn(
    'screen',
    [
      '-m', '-d',
      '-S', `serverscreen${server.id}`,
      'wine',
        (args.disableWSE === true) ? 'mb_warband_dedicated.exe' : 'WSELoaderServer.exe',
        '-r', `Configs/${args.config}`,
        '-m', `${args.module}`
    ],
    {
      cwd: currentGameserverPath,
      detached: true,
      stdio: 'ignore'
    }
  );

  program.unref();


  server.gameserverLastModule = args.module;
  server.gameserverLastConfig = args.config;
  await server.save();

  return server;
}

我在浏览 SO 时发现了一个新线索:

  • Using -L will create a log file.
  • 包含的日志文件,wine: /home/tsm/.wine is not owned by you
  • The resolution to that is to do sudo chown -R root: ~/.wine。这是因为我运行 web 服务器作为 root 获得端口 80 perms,所以它以 root 启动 wine,所以 root 必须拥有 .wine 文件夹。