Как мне дать эту команду оболочки в Swift 5 с правами администратора? - PullRequest
1 голос
/ 08 июля 2020

Пытаюсь сделать GUI для инструмента YouTube-dl. (YouTube-dl.org) Я использую эту функцию Shell для выполнения необходимых команд:

func shell(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()
    task.standardOutput = pipe
    task.arguments = ["-c", command]
    task.launchPath = "/bin/bash"
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)!
    return output

Это код, который я написал для запуска YouTube-dl при нажатии кнопки, дайте ему YouTube URL-адрес и сохраните загруженное видео на рабочий стол:

 @IBAction func actionMP4(_ sender: Any) {
        
    shell("/usr/local/bin/youtube-dl -o ~/Desktop/DownloadedVideo.mp4 https://youtu.be/pUECdF7KCN4")
         
        
    }

Когда я запускаю программу и нажимаю кнопку, связанную с приведенным выше кодом, я получаю эту ошибку:

    /bin/bash: /usr/local/bin/youtube-dl: Operation not permitted

Как сделать Я разрешаю?

Спасибо.

1 Ответ

2 голосов
/ 08 июля 2020

Если целью приложения является поддержка загрузки видео с YouTube, ему, вероятно, не нужны повышенные привилегии. Если этого требует Youtube-dl, он может быть не лучшим кандидатом для внутренней серверной части приложения Ma c. Лучшим выбором может быть реализация его функциональности и / или поиск альтернативных API, которые позволят вам сделать это без повышенных привилегий (или python зависимости, если на то пошло).

Тем не менее, если вы действительно хотите запустите внешний инструмент с повышенными привилегиями, вам нужно будет использовать XP C для создания привилегированного вспомогательного инструмента и разрешить пользователю запускать его от имени администратора во время выполнения. Этот API немного эволюционировал в последних нескольких выпусках ОС и, в некоторой степени, по замыслу, я думаю, его нетривиально реализовать.

Большинство примеров кода находится в Objective- C, поэтому вам нужно научитесь пользоваться API-интерфейсами Objective- C от Swift - или напишите код повышения прав в Objective- C и оберните его в класс, который вы можете легко вызвать из Swift. Оболочка расширенного инструмента запускается как XPCService с помощью launchd, и ваше приложение связывается с ним через порт mach.

Полный код и настройка проекта выходят за рамки того, что будет соответствовать этому ответу, но вот пример метода настройки, реализованного в Objective- C, сокращенный от кода EvenBetterAuthorizationSample (комментарии и диагностические c прагмы удалены):

- (void)connectWithEndpointAndAuthorizationReply:(void(^)(NSXPCListenerEndpoint * endpoint, NSData * authorization))reply
{
    [self.queue addOperationWithBlock:^{

        if (self.helperToolConnection == nil) {
            self.helperToolConnection = [[NSXPCConnection alloc] initWithMachServiceName:kHelperToolMachServiceName options:NSXPCConnectionPrivileged];
            self.helperToolConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperToolProtocol)];
 
            self.helperToolConnection.invalidationHandler = ^{

                self.helperToolConnection.invalidationHandler = nil;
                [self.queue addOperationWithBlock:^{
                    self.helperToolConnection = nil;
                    NSLog(@"connection invalidated");
                }];
            };
            [self.helperToolConnection resume];
        }

        [[self.helperToolConnection remoteObjectProxyWithErrorHandler:^(NSError * proxyError) {
            NSLog(@"connect failed: %@ / %d", [proxyError domain], (int) [proxyError code]);
            reply(nil, nil);
        }] connectWithEndpointReply:^(NSXPCListenerEndpoint *replyEndpoint) {
            reply(replyEndpoint, self.authorization);
        }];
    }];
}

А вот текущая ссылка на полную пример проекта: https://developer.apple.com/library/archive/samplecode/EvenBetterAuthorizationSample/Introduction/Intro.html

В ветке форума разработчиков Apple говорится, что это должно быть возможно из Swift: https://developer.apple.com/forums/thread/99151

Вот еще один SO резьба на топи c: Приложение, Связь с помощником

...