2009-11-29 6 views
1

Je voudrais exécuter un script shell, à partir d'un fichier ou d'une chaîne objective-c (dans le code). J'aimerais aussi que le résultat du script shell soit stocké dans une variable. Je ne voudrais pas que le script shell soit divisé en arguments (comme setLaunchPath quand je l'exécute). Par exemple: en exécutant ce script shell "mount_webdav idisk.mac.com/mac_username/Volumes/mac_username" au lieu de "/ bin/mount_webdav" alors les arguments. Est-ce qu'il y a un moyen de faire ça? J'utilise NSTask en ce moment, mais cela m'a causé quelques erreurs quand j'essaye de mettre les arguments avec. Voici le code posé:Obtenir le résultat du script shell objectif-c

(une partie du fichier .m)

NSString *doshellscript(NSString *cmd_launch_path, NSString *first_cmd_pt) { 

NSTask *task = [[NSTask alloc] init]; // Make a new task 

[task setLaunchPath: cmd_launch_path]; // Tell which command we are running 

[task setArguments: [NSArray arrayWithObjects: first_cmd_pt, nil]]; 

[task setArguments: first_cmd_pt]; 

NSPipe *pipe = [NSPipe pipe]; 

[task setStandardOutput: pipe]; 

[task launch]; 

    NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; 

    NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; 

    [task release]; //Release the task into the world, thus destroying it. 

    return string; 
} 


NSString *mount_idisk(NSString *mac_username) { 

doshellscript(@"/bin/mkdir", [@"/Volumes/" stringByAppendingString:mac_username]); 

NSString *path_tmp = [mac_username stringByAppendingString: @"/ /Volumes/"]; 

NSString *idisk_path = [path_tmp stringByAppendingString:mac_username]; 

//NSLog(@"%@", [@" http://idisk.mac.com/" stringByAppendingString: idisk_path]); 

NSString *finished_path = [@"http://idisk.mac.com/" stringByAppendingString: idisk_path]; 

doshellscript(@"/sbin/mount_webdav", finished_path); 
} 

... Voici la ligne que je me sers pour l'exécuter: mount_idisk("username");

Répondre

5

Il n'y a aucun moyen pour passer une ligne de commande entière à NSTask.

Pour une bonne raison; Ce faisant, il y a beaucoup de trous de sécurité si vous avez une sorte de composition de cordes. Votre code de composition de chaîne devrait être pleinement conscient de toutes les règles d'analyse d'une ligne de commande shell et devrait échapper à toutes les combinaisons possibles de caractères qui pourraient conduire à l'exécution de commandes arbitraires. L'API C system() vous permet d'exécuter des commandes arbitraires, mais n'a aucun mécanisme pour capturer la sortie directement. Il serait facile d'ajouter quelque chose à votre ligne de commande qui crache la sortie dans un fichier temporaire que vous lirez plus tard, mais cela ajoute juste plus de trous de sécurité au-delà de transmettre une ligne de commande entière comme une seule chaîne.

Attendez ... On dirait que vous avez un bug simple:

[task setArguments: [NSArray arrayWithObjects: first_cmd_pt, nil]]; 
[task setArguments: first_cmd_pt]; 

Pourquoi définissez-vous et réinitialisant les arguments de la tâche?

Étant donné que votre fonction est mount_idisk() compose efficacement les arguments individuels et les concaténer ensemble en une seule chaîne, pourquoi ne pas vous farcir simplement tous les args dans un NSArray et de modifier doshellscript() prendre un tableau comme second paramètre; le tableau des arguments?


Vous ne créez pas le tableau d'arguments correctement.

A savoir:

NSArray *finished_path = [NSArray arrayWithObjects:@"http://idisk.mac.com/", mac_username, @"/ /Volumes/", mac_username, nil]; 

Cette ligne crée un tableau 4 contiennent des objets qui sont ensuite traités comme 4 arguments séparés dans la fonction doshellscript() et non pas les deux arguments que vous avez besoin.

Peut-être quelque chose comme:

NSString *mobileMeUserURL = [@"http://idisk.mac.com/" stringByAppendingString: mac_username]; 
NSString *localMountPath = [ @"/ /Volumes/" stringByAppendingString: mac_username]; 
NSArray *arguments = [NSArray arrayWithObjects: mobileMeUserURL, localMountPath, nil]; 
+0

@ bbum: Voulez-vous dire que vous ne pouvez exécuter une commande à l'époque avec NSTask? – eonist

+0

@GitSyncApp Correct. NSTask permet l'exécution externe d'une seule commande. Créez plusieurs instances, une pour chaque commande. Si vous devez effectuer une sorte de piping entre les processus, écrivez un script shell dans un fichier temporaire et exécutez-le. – bbum

+0

@ bbum: Qu'en est-il de l'appel d'un shellscript qui à son tour appelle plusieurs commandes? – eonist

Questions connexes