2010-08-18 17 views
1

J'essaie de déboguer une application C++ qui appelle de nombreuses applications en ligne de commande telles que grep, etc via un appel système system(). J'ai besoin de voir toutes les commandes que l'application exécute via l'appel system().Comment enregistrer toutes les commandes exécutées par system() Appel système

J'ai essayé d'afficher ces commandes en activant l'historique et en affichant le fichier .history. Mais ces commandes ne sont pas exécutées via un terminal. Le fichier historique n'a que les commandes exécutées de manière interactive.

Une idée de comment cela peut-il être fait?

Répondre

3

Pour tracer chaque commande exécutée par "yourProgram":

truss -s!all -daDf -t exec yourProgram 

par exemple:

$ truss -s!all -daDf -t exec sh -c "/bin/echo hello world;/bin/date" 
Base time stamp: 1282164973.7245 [ Wed Aug 18 22:56:13 CEST 2010 ] 
5664: 0.0000 0.0000 execve("/usr/bin/i86/ksh93", 0x080471DC, 0x080471EC) argc = 3 
5664: argv: sh -c /bin/echo hello world;/bin/date 
5665: 0.0106 0.0106 execve("/bin/echo", 0x08067484, 0x080674F8) argc = 3 
5665: argv: /bin/echo hello world 
hello world 
5664: 0.0126 0.0126 execve("/bin/date", 0x080674E0, 0x080674F8) argc = 1 
5664: argv: /bin/date 
Wed Aug 18 22:56:13 CEST 2010 

Si vous souhaitez établir une corrélation entre ces execs au système() appelle, vous pouvez utiliser cette commande:

truss -t execve -f -u 'libc:system' yourProgram 

par exemple:

$ cat a.c 
main() 
{ 
system("echo a b c"); 
system("pwd"); 
} 

$ truss -t execve -f -u 'libc:system' ./a 
20073: execve("a", 0x08047240, 0x08047248) argc = 1 
20073/[email protected]: -> libc:system(0x8050a5c, 0x0) 
20074/1: execve("/bin/sh", 0x080471BC, 0x08047248) argc = 3 
a b c 
20073/[email protected]: <- libc:system() = 0 
20073/[email protected]: -> libc:system(0x8050a68, 0x0) 
20076/1: execve("/bin/sh", 0x080471BC, 0x08047248) argc = 3 
/tmp 
20073/[email protected]: <- libc:system() = 0 

Enfin, si vous êtes en utilisant Solaris 10 ou plus récent, vous pouvez utiliser Dtrace pour cette tâche comme ceci:

dtrace -Z -q -c yourProgram -n ' pid$target:libc:system:entry { printf("system(\"%s\")\n", copyinstr(arg0)); } ' 

qui donnera cette sortie avec le même « un » code:

a b c 
/tmp 
system("echo a b c") 
system("pwd") 

PS: Par le système de navigation() n'est pas un appel système, mais une fonction de bibliothèque standard.

+0

@jlliagre Exactement ce que je cherchais! Noté sur le système() Merci :) – Raj

2

Vous pouvez utiliser la fonction Truss ou Strace (impossible de savoir laquelle est fournie avec Solaris) pour exécuter le programme et suivre les appels vers le système.

Pour ferme la commande correspondante sera quelque chose comme truss -caf program_name

+0

Le tri traiterait-il les invocations 'system()' en soi * ou, à la place, comme les lignes de Linux, afficherait les appels système constitutifs (par exemple, 'fork()' et 'exec()')? – pilcrow

+0

@pilcrow. Vous avez raison, il affichera les appels système sous-jacents que vous pourriez filtrer uniquement pour les appels exec en utilisant des arguments de truss.Cela fait TRES longtemps depuis que je l'ai utilisé mais vous pouvez obtenir une liste de tous les execs et les arguments qui y sont passés très facilement. Alors que l'OP demande des appels à system(), je ne suis pas entièrement sûr, sans connaître le contexte, s'ils veulent qu'une instance "fork/exec" spécifique soit incluse ou non. –

+0

Solaris Truss peut également tracer des appels de fonction de bibliothèque, bien qu'il n'affiche pas leurs arguments. Voir mon autre réponse pour plus de détails. – jlliagre

5

Définir une nouvelle macro avec un nom semblable:

#define system(_x) std::cout << _x << std::endl; (system)(_x); 

La macro system remplace la fonction system et:

  1. imprime la commande à la sortie standard (ou ailleurs). Il appelle la fonction system.

Merci à la suggestion de Hasturkun, ce qui suit est mieux:

#define system(_x) (std::cout << (_x) << std::endl, system(_x)) 

qui renvoie le résultat de l'appel system fonction aussi ;-)

+1

Vous pourriez vouloir le changer en quelque chose comme '#define system (_x) (std :: cout << (_x) << std :: endl, system (_x))' pour qu'il renvoie toujours une valeur. – Hasturkun

+0

@Hasturkun: Merci. J'ai oublié que le résultat de l'appel de la fonction 'system' pourrait être demandé dans le code. –

+0

@Hasturkun: Dans la définition de la macro 'system', l'appel de la fonction' system' doit être entouré de parenthèses pour empêcher la macro 'system' de s'auto-appeler récursivement. –