2012-04-03 17 views
8

Qui ho scritto un programma C che esegue il file hi.sh utilizzando la chiamata system.Ottieni le variabili di ambiente utilizzando il codice C

Qui ho usato . ./hi.sh quindi voglio eseguire questo script nella stessa shell e quindi provare a ottenere la variabile di ambiente utilizzando la funzione getenv, ma qui sto ottenendo output diverso da quello che mi aspettavo.

Il file hi.sh contiene

export TEST=10 
return 

significa che quando si esegue questo file hi.sh utilizzando la chiamata di sistema, la sua export TEST imposta il valore di 10 nella stessa shell. Dopo questo, sto cercando di ottenere questo valore variabile ma il suo valore NULL dato.

E se eseguo questo script manualmente dalla console come . ./hi.sh, allora funziona correttamente e ottengo il valore 10 TEST utilizzando la funzione getenv("TEST").

Codice:

#include <stdio.h> 
int main() 
{ 
    system(". ./hi.sh"); 
    char *errcode; 
    char *env = "TEST"; 
    int errCode;  
    errcode = getenv(env); 
    printf("Value is = %s\n",errcode); 
    if (errcode != NULL) { 
     errCode =atoi(errcode); 
     printf("Value is = %d\n",errCode); 
    } 
} 

uscita:

Value is = (null) 

Come posso esportare variabile TEST in guscio programma? Se system() esegue comandi in shell diverse, come posso utilizzare il codice di programma C per ottenere una variabile di ambiente che viene esportata dalla shell richiamata tramite una chiamata system()?

risposta

7

Come al solito, la pagina man lo spiega, ma è necessario leggerlo con molta attenzione.

DESCRIPTION 
     system() executes a command specified in command by calling /bin/sh -c 
     command, and returns after the command has been completed. During exe‐ 
     cution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT 
     will be ignored. 

In altre parole, il sistema() prima di avviare/bin/sh, e poi ha/bin/sh iniziare qualsiasi comando che si desidera eseguire. Quindi, quello che succede qui è che la variabile TEST viene esportata nella shell/bin/sh la chiamata di system() inizia implicitamente, ma non al programma che ha chiamato system().

+0

Quindi, come posso ottenere questo obiettivo? – user1089679

+0

Come posso esportare la variabile TEST per programmare Shell? – user1089679

+2

@ user1089679 Crea il tuo script (imposta l'ambiente) prima di eseguire il tuo programma C. Ecco come sono state progettate le variabili di ambiente da utilizzare. –

0

è possibile impostare la variabile d'ambiente nel proprio processo utilizzando setenv() (che system() poi passa in silenzio a processi figli, o esplicitamente passare le variabili utilizzando fork() e execve() per eseguire lo script di shell.

+0

grazie per la tua risposta. Ma devo chiamare shell script usando la chiamata di sistema e il suo necessario per impostare le variabili di ambiente dallo script. Dopo questo voglio ottenere variabili di ambiente dalla shell – user1089679

+2

Ciò non è possibile. Le variabili possono essere passate solo ai processi appena creati, non al processo padre. Lo script dovrebbe generare un output, che puoi recuperare usando 'popen()' invece di 'system()'. –

9

Il bambino processo non può impostare direttamente l'ambiente del processo padre. l'approccio con system() e getenv() è destinato a fallire, quindi.

Se si sta tentando di importare variabili selezionate fissati dallo script hi.sh, allora avete un paio di scelte. O si può leggere lo script hi.sh e calcolare a cosa li imposterà (piuttosto difficile), oppure è possibile eseguire lo script e fare in modo che il codice che si esegue riporti indietro sulle variabili di interesse.

Supponi che hi.sh set $ENV1 e $ENV2. È possibile utilizzare popen() per ripristinare i valori nel programma e setenv() per impostare l'ambiente del programma.A grandi linee:

FILE *fp = popen(". ./hi.sh; echo ENV1=$ENV1; echo ENV2=$ENV2", "r"); 

while (fgets(buffer, sizeof(buffer), fp) != 0) 
{ 
    ...split the buffer into env_name, env_value... 
    setenv(env_name, env_value); 
} 

pclose(fp); 

nota che ho inserito il nome della variabile nelle informazioni riecheggiata; questo semplifica la vita. Se il tuo elenco di variabili diventa ingombrante, forse esegui ". ./hi.sh; env" per ottenere l'intero ambiente, quindi leggi ogni riga e escogita dall'elenco incorporato se è un'impostazione variabile che desideri utilizzare o meno. Oppure puoi semplicemente impostare di nuovo l'intero ambiente, se ciò ti piace. È necessario verificare che la funzione setenv() abbia avuto esito positivo (restituisce zero quando ha esito positivo). Si dovrebbe anche verificare che lo popen() abbia avuto successo (fp != 0). In questo contesto, probabilmente è possibile utilizzare strtok() per cercare il = che separa il nome della variabile dal valore; calpesta un byte null sopra la =, dando un null terminata nome e un valore terminato nullo:

char *env_name = strtok(buffer, "="); 
    char *env_value = buffer + strlen(env_name) + 1; 
    if (setenv(env_name, env_value) != 0) 
     ...report trouble... 
1

Un'altra possibile soluzione è quella di avere il vostro programma exec stesso attraverso un'altra shell. Quella shell sostituisce il programma in esecuzione, quindi legge le variabili d'ambiente e quindi sostituisce la shell con una nuova copia del programma. Devi dire alla nuova copia che ha già eseguito un exec o lo farà solo ripetutamente. È possibile cercare la variabile di ambiente o passare un flag della riga di comando.

Un esempio non testata:

execl("/bin/sh", "-c", ". ./hi.sh; exec ./a.out --envset", NULL); 

Si avrebbe bisogno di sostituire a.out con qualunque sia il nome vero programma è. Probabilmente vorrai estrarlo da argv [0] e anche passare il resto dell'array argv. Ma devi riformattare gli argomenti per funzionare come argomenti della shell, quindi devono essere citati come necessario, ecc.

Problemi correlati