【发布时间】:2011-11-27 14:56:10
【问题描述】:
我写了一个 FTP 服务器,女巫是通过 ftpd.command 从命令行启动的。 现在我想从 Cocoa 应用程序运行该命令。
我想退出应用程序并且命令应该保持运行。 当我返回 Cocoa 应用程序时,它应该知道 FTP 服务器是否仍在运行。
有人可以帮助我吗? 非常感谢! 朱利安
【问题讨论】:
标签: macos cocoa daemon launchd
我写了一个 FTP 服务器,女巫是通过 ftpd.command 从命令行启动的。 现在我想从 Cocoa 应用程序运行该命令。
我想退出应用程序并且命令应该保持运行。 当我返回 Cocoa 应用程序时,它应该知道 FTP 服务器是否仍在运行。
有人可以帮助我吗? 非常感谢! 朱利安
【问题讨论】:
标签: macos cocoa daemon launchd
您应该使用launchd 来处理 FTP 服务器。它专为您描述的情况而设计,即启动和管理后台服务。
您需要创建一个launchd 配置文件,可以将其放置在以下位置之一:
~/Library/LaunchAgents:用户提供的每用户代理。/Library/LaunchAgents:管理员提供的每用户代理。/Library/LaunchDaemons:系统范围的守护进程由
管理员。守护进程 是一种系统范围的服务,所有客户端都有一个实例。 代理是一种按用户运行的服务。
launchd Configuration files 采用property list. 的形式
您需要创建一个launchd 配置plist 并将其放置在上述位置之一。您可以配置 plist,以便 launchd 在启动时或定期运行您的服务,或响应各种操作(例如更改文件夹的内容)。
要检查您的作业是否正在运行,您需要使用Service Management framework。您可以向launchd 询问您的工作状态,如下所示:
CFDictionaryRef jobDict = SMJobCopyDictionary(kSMDomainUserLaunchd, CFSTR("com.your.apps.bundle.id"));
如果找不到工作,则jobDict 将是NULL。
(如果您使用的是系统级守护程序,则可以将 kSMDomainUserLaunchd 替换为 kSMDomainSystemLaunchd)。
【讨论】:
我认为您必须调整您的 FTP 服务器,使其在完成之前不会“阻塞”命令行。我在这里找到了一些示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
void start_daemon(void)
{
chdir("/");
setsid();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDWR);
dup(STDIN_FILENO);
dup(STDIN_FILENO);
for(;;)
sleep(100);
}
int main(int argc, char *argv[])
{
pid_t pid;
if ((pid = fork()) < 0)
{
perror("fork() failed");
return 1;
}
if (pid == 0)
start_daemon();
printf("Child has PID %i.\n", pid);
return 0;
}
【讨论】:
在 GitHub 上查看我的项目 TabletMagic 的源代码。它有一个启动用户空间守护进程的 Cocoa 首选项窗格,此外它还管理一个启动项。 Cocoa 部分使用外部助手来完成所有特权任务,该任务在第一次启动时是自设置的 - 在 Cocoa 应用程序要求管理员授权的特权上下文中。这都是标准程序,尽管不是纯 Cocoa。
【讨论】: