Operation Not Permitted When Executing 'Killall' with Swift

Operation not permitted when executing 'killall' with Swift

Mac apps, like iOS apps, are sandboxed by default, which means they have very limited access to system resources. They are only allowed to read and write to a small number of sandboxed directories, for example, and read/write/execute from usr/bin is most definitely not allowed, and nor will you be allowed to launch processes.

As I recall, by deleting your entitlements file you are building an app that isn't sandboxed. You can run it from Xcode, but will need to change your system settings in order to be able to run it from the finder.

Kill process in swift

I'd suggest you first read the man page for sysctl -- it's used to get and set kernel state. Does that sound like something you want?

The path to killall is /usr/bin/killall, which you can find from Terminal:

> which killall
/usr/bin/killall

Here's the full Swift code:

let pipe = Pipe()

let task = Process()
task.launchPath = "/usr/bin/killall"
task.arguments = ["iTunes"]
task.standardOutput = pipe
task.standardError = pipe
task.launch()
task.waitUntilExit()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
if let output = String(data: data, encoding: .utf8) {
print(output)
}

Execute a terminal command from a Cocoa app

You can use NSTask. Here's an example that would run '/usr/bin/grep foo bar.txt'.

int pid = [[NSProcessInfo processInfo] processIdentifier];
NSPipe *pipe = [NSPipe pipe];
NSFileHandle *file = pipe.fileHandleForReading;

NSTask *task = [[NSTask alloc] init];
task.launchPath = @"/usr/bin/grep";
task.arguments = @[@"foo", @"bar.txt"];
task.standardOutput = pipe;

[task launch];

NSData *data = [file readDataToEndOfFile];
[file closeFile];

NSString *grepOutput = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (@"grep returned:\n%@", grepOutput);

NSPipe and NSFileHandle are used to redirect the standard output of the task.

For more detailed information on interacting with the operating system from within your Objective-C application, you can see this document on Apple's Development Center: Interacting with the Operating System.

Edit: Included fix for NSLog problem

If you are using NSTask to run a command-line utility via bash, then you need to include this magic line to keep NSLog working:

//The magic line that keeps your log where it belongs
task.standardOutput = pipe;

An explanation is here: https://web.archive.org/web/20141121094204/https://cocoadev.com/HowToPipeCommandsWithNSTask

How do I run a terminal command in a Swift script? (e.g. xcodebuild)

If you don't use command outputs in Swift code, following would be sufficient:

#!/usr/bin/env swift

import Foundation

@discardableResult
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}

shell("ls")
shell("xcodebuild", "-workspace", "myApp.xcworkspace")

Updated: for Swift3/Xcode8



Related Topics



Leave a reply



Submit