Как запускать команды оболочки из приложения Mac/MacRuby?

Я пытаюсь написать небольшое приложение строки состояния MacRuby, которое запускает команду из командной строки и отображает вывод. Я не знаю, как это сделать. Как я могу сделать это из моего приложения Mac?

Обновление. Еще одна вещь, которую может потребоваться, это запросить пароль администратора. Иногда, когда я запускаю этот скрипт из командной строки, он запрашивает мой пароль. Я не знаю, как запросить у пользователя пароль (или встроить оболочку, чтобы он мог ввести его напрямую).


person Andrew    schedule 19.12.2011    source источник
comment
Что именно делает ваш скрипт?   -  person ghstcode    schedule 19.12.2011
comment
В конце концов, это будет оболочка с графическим интерфейсом для vagrant. Поэтому мне нужно будет запустить vagrant up и посмотреть результат.   -  person Andrew    schedule 19.12.2011


Ответы (2)


Используя Cocoa и MacRuby, используйте NSTask. Пример, который выполняет ls -la и выводит вывод:

framework 'Cocoa'

task = NSTask.alloc.init
task.setLaunchPath("/bin/ls")

arguments = NSArray.arrayWithObjects("-l", "-a", nil)
task.setArguments(arguments)

pipe = NSPipe.pipe
task.setStandardOutput(pipe)

file = pipe.fileHandleForReading

task.launch

data = file.readDataToEndOfFile

string = NSString.alloc.initWithData(data, encoding: NSUTF8StringEncoding)
puts "Command returned: "
puts string

К сожалению, включение прав администратора — нетривиальная задача, особенно при использовании MacRuby. Взгляните на структуру SecurityFoundation и этот ссылка. По сути, вам нужно позвонить

AuthorizationExecuteWithPrivileges(...)

с настроенным AuthorizationRef, путем запуска инструмента, флагами, аргументами. Полезный пример здесь (в ObjC ), показывающий, как это работает.

person jtomschroeder    schedule 16.02.2012
comment
Спасибо! Что помогает! Насколько я могу судить, это будет блокироваться до завершения. Есть ли способ асинхронно запустить команду и обновить пользовательский интерфейс при выводе каждой строки? - person Andrew; 16.02.2012
comment
Для асинхронного обновления вы можете использовать readInBackgroundAndNotify или отслеживать StandardOutput в другом потоке. - person jtomschroeder; 16.02.2012

Вы можете просто использовать обратные кавычки:

output = `cd ~ && ls`
puts output # or assign to a label, textbox etc.

Если для запуска вашей команде требуются права администратора, она вообще не запустит команду и не вернет ответ.

person ghstcode    schedule 19.12.2011
comment
Похоже, это может сработать, но мне нужно придумать решение, которое позволит мне запрашивать у пользователя пароль. Когда я запускаю из командной строки, иногда в середине сценария он пытается сделать что-то, что требует прав администратора, поэтому он запрашивает у пользователя пароль. - person Andrew; 19.12.2011
comment
как насчет того, чтобы попытаться прочитать защищенный системный файл внутри вашего метода main() target-c непосредственно перед macruby_main(). Это приведет к принудительной авторизации. - person ghstcode; 20.12.2011