Objective C 运行 通过 OSX Cron 命令失败

Objective C Command Failing When Run Through OSX Cron

我编写了一个独立的 Objective C 命令应用程序。如果我通过 LaunchDaemon 运行 它,当 ObjC 客户端应用程序通过 DistriutedObjects 通信连接时它 运行 就好了。如果我在命令行 运行 它,它 运行 就好了。如果我 运行 它在被 Bash 脚本调用时,它 运行 就好了。但是,我尝试通过 root 用户的 crontab 运行 以各种方式执行此操作,它会生成有关指针分配的崩溃报告:

Apr 14 05:27:00 volomike cron[72531]: cron(72531,0x7fff7d2fa000) malloc: *** error for object 0x7fb9c8400213: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
Apr 14 05:27:00 volomike diagnosticd[70689]: error evaluating process info - pid: 72531, puniqueid: 72531
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.vix.cron[72531]): Service exited due to signal: Abort trap: 6
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.apple.ReportCrash.Root[72550]): Endpoint has been activated through legacy launch(3) APIs. Please switch to XPC or bootstrap_check_in(): com.apple.ReportCrash.DirectoryService
Apr 14 05:27:00 volomike ReportCrash[72550]: Saved crash report for cron[72531] version 39 to /Library/Logs/DiagnosticReports/cron_2016-04-14-052700_volomike.crash

该崩溃报告的重要部分如下:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
abort() called
*** error for object 0x7fb9c8400213: pointer being freed was not allocated


Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff9490ff06 __pthread_kill + 10
1   libsystem_pthread.dylib         0x00007fff9c45e4ec pthread_kill + 90
2   libsystem_c.dylib               0x00007fff9345b6e7 abort + 129
3   libsystem_malloc.dylib          0x00007fff9c02f041 free + 425
4   cron                            0x000000010367aa41 0x103677000 + 14913
5   cron                            0x000000010367a7e4 0x103677000 + 14308
6   cron                            0x0000000103679572 0x103677000 + 9586
7   cron                            0x000000010367925a 0x103677000 + 8794
8   cron                            0x000000010367885e 0x103677000 + 6238
9   libdyld.dylib                   0x00007fff949835ad start + 1

以各种方式,我已经用这些不同的 cron 行完成了,但是当尝试调用命令时它们立即崩溃,甚至当我有 NSLog() 写东西到 /var/log/system.log 时从 main 的开始到应用程序的结束,没有任何东西被写入——就像当 cron 试图调用我的命令时,它立即死掉,并出现关于指针分配的崩溃报告。

41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched

41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched &

41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched

41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched &

再次注意,如果我 '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched,它 运行 就好了,/bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched'/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched

我什至做了一个变体,其中 cron 调用我的 mytoolcommand.sh 脚本并将 Hello World 简单地写到 /tmp/out.txt,它 运行 就好了。所以,我知道我的 crontab 正在工作。

你能帮我弄清楚我做错了什么吗?一些疑似可能的问题:

发展

我怀疑 El Capitan Gatekeeper 可能是原因。因此,我在 main.mm 文件中创建了一个简单的 Objective C 控制台应用程序并进行了编译。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *sTest = @"Hello World";
        [sTest writeToFile:@"/tmp/test.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    return 0;
}

Cron 似乎 运行 这很好,所以看起来不像是 Gatekeeper 问题。

我让问题消失了,但只是短暂地消失了。我在 b运行d 新项目中重新编译了该项目,复制了源代码和设置。然后,我 运行 通过 cron 命令执行了大约 4 次,没有任何问题。然而,当我运行它第五次时,它再次失败并继续失败。

所以,我想我必须弄清楚如何将其转换为 LaunchAgent。

答案是你不知道。在 OSX 上,您不再为正在编码的应用程序使用 cron。相反,切换到 LaunchAgent。当然,Apple 保留它是为了 POSIX 支持,因此可能会保留很长时间,但即使是他们的网站也鼓励人们不再使用 cron 进行应用程序编码。

"Note: Although it is still supported, cron is not a recommended solution. It has been deprecated in favor of launchd."

SOURCE: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html

不幸的是,LaunchAgents 还不支持(至少在 10.11.4 中)cron-style 语法。 (是的,我已经为您向 Apple 提交了该建议。)因此,没有使用破折号、逗号或反斜杠。相反,它只支持一个整数和多个块来创建每个时间帧。如果这还不够合适,那么至少设置最短的时间范围,然后在您要启动的任何内容中执行其余代码,例如,如果您只想在第一个星期一 运行当月,LaunchDaemon 在前 7 天启动,但如果不是当月的第一个星期一,您的应用程序会关闭。