Si j'examine, /proc/1/environ
je peux voir une chaîne délimitée par des octets null 1
des variables d'environnement du processus . Je voudrais introduire ces variables dans mon environnement actuel. Y a-t-il un moyen facile de faire ceci?
La proc
page de manuel me donne un extrait qui aide à imprimer chaque variable d'environnement ligne par ligne (cat /proc/1/environ; echo) | tr '\000' '\n'
. Cela m'aide à vérifier que le contenu est correct, mais ce que je dois vraiment faire, c'est source ces variables dans ma session bash actuelle.
Comment je fais ça?
la source
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, qui gérera également les variables avec des guillemets correctement."$@"
au lieu de'{}'
. Pour ceux qui s'interrogent sur l'--
argument de sa réponse améliorée: les arguments de position àbash -c command_string
sont attribués à partir de$0
, tandis que se"$@"
développe pour inclure les arguments à partir de$1
. L'argument--
est affecté à$0
.Dans
bash
vous pouvez faire ce qui suit. Cela fonctionnera pour tous les contenus possibles des variables et éviteraeval
:Cela déclarera les variables lues comme variables shell dans le shell en cours d'exécution. Pour exporter les variables dans l'environnement shell en cours d'exécution à la place:
la source
Dans cette réponse, je suppose un système où
/proc/$pid/environ
renvoie l'environnement du processus avec le PID spécifié, avec des octets nuls entre les définitions de variables. ( Donc Linux, Cygwin ou Solaris (?) ).Zsh
(Assez simple comme le fait zsh: une redirection d'entrée sans commande
<FILE
est équivalente àcat FILE
. La sortie de la substitution de commande subit une expansion des paramètres avec les drapeauxps:\000:
signifiant "divisé en octets nuls" et@
signifiant "si le tout est entre guillemets, alors traitez chaque élément du tableau comme un champ séparé »(généralisation"$@"
).)Bash, mksh
(Dans ces shells, un délimiteur vide transmis à
read
des octets nuls étant des séparateurs. J'utilisePWD
comme nom de variable temporaire pour éviter d'altérer une autre variable qui pourrait finir par être importée. Bien que vous puissiez techniquement importerPWD
, elle ne resterait en place que jusqu'à ce que le suivantcd
.)POSIX
La portabilité POSIX n'est pas intéressante pour cette question, car elle ne s'applique qu'aux systèmes qui en ont
/proc/PID/environ
. La question est donc de savoir ce que Solaris sed prend en charge - ou si Solaris a/proc/PID/environ
, il ne l'a pas utilisé auparavant, mais je suis loin derrière la courbe des fonctionnalités de Solaris, ce qui pourrait le cas de nos jours. Sous Linux, les utilitaires GNU et BusyBox sont tous deux sans danger, mais avec des mises en garde.Si nous insistons sur la portabilité POSIX, aucun des utilitaires de texte POSIX n'est requis pour gérer les octets nuls, c'est donc difficile. Voici une solution qui suppose que awk prend en charge un octet nul comme délimiteur d'enregistrement (nawk et gawk le font, tout comme BusyBox awk, mais pas mawk).
BusyBox awk (qui est la version couramment trouvée sur les systèmes Linux embarqués) prend en charge les octets nuls mais ne se définit
RS
pas"\0"
dans unBEGIN
bloc et pas la syntaxe de ligne de commande ci-dessus; mais il prend en charge-v 'RS="\0"'
. Je n'ai pas cherché pourquoi, cela ressemble à un bogue dans ma version (Debian wheezy).(Enveloppez toutes les
lignesdes enregistrements séparés par des"\047"
valeurs nulles entre guillemets simples , après avoir échappé les guillemets simples à l'intérieur des valeurs.)Avertissements
Sachez que l'un de ces paramètres peut tenter de définir des variables en lecture seule (si votre shell possède des variables en lecture seule).
la source
J'ai tourné en rond avec ça. J'étais frustré par la portabilité des octets nuls. Cela ne me convenait pas qu'il n'y avait aucun moyen fiable de les manipuler dans une coquille. J'ai donc continué à chercher. La vérité est que j'ai trouvé plusieurs façons de le faire, dont seulement quelques-unes sont mentionnées dans mon autre réponse. Mais les résultats ont été au moins deux fonctions shell qui fonctionnent comme ceci:
Je vais d'abord parler de la
\0
délimitation. C'est en fait assez facile à faire. Voici la fonction:Fondamentalement
od
prendstdin
et écrit à sonstdout
chaque octet qu'il reçoit en hexadécimal une par ligne.Je parie que vous pouvez deviner quel est le
\0null
bon, non? Écrit comme ça, il est facile à manipuler avec toutsed
.sed
enregistre simplement les deux derniers caractères de chaque ligne jusqu'à ce qu'il rencontre une valeur nulle à quel point il remplace les sauts de ligne intermédiaires parprintf
un code de format convivial et imprime la chaîne. Le résultat est un\0null
tableau délimité de chaînes d'octets hexadécimales. Regardez:J'ai expliqué ce qui précède pour
tee
que vous puissiez voir à la fois la sortie de la substitution de commande et le résultat duprintf
traitement de. J'espère que vous remarquerez que le sous-shell n'est pas cité non plus, mais qu'il estprintf
toujours divisé uniquement au niveau du\0null
délimiteur. Regardez:Aucune citation sur cette extension non plus - peu importe si vous la citez ou non. Cela est dû au fait que les valeurs de morsure ne sont pas séparées, à l'exception de la ligne
\n
électronique générée pour chaque fois quised
imprime une chaîne. Le fractionnement de mots ne s'applique pas. Et c'est ce qui rend cela possible:La fonction ci-dessus utilise
_zedlmt
soit${pcat}
un flux préparé de code d'octet pour l'approvisionnement de l'environnement de tout processus qui peut être trouvé dans/proc
, soit directement.dot
${psrc}
le même dans le shell actuel, ou sans paramètre, pour afficher une sortie traitée de celui-ci vers le terminal commeset
ou leprintenv
fera. Tout ce dont vous avez besoin est d'un$pid
- n'importe quel/proc/$pid/environ
fichier lisible fera l'affaire.Vous l'utilisez comme ceci:
Mais quelle est la différence entre convivial et sourcable ? Eh bien, la différence est ce qui rend cette réponse différente de toutes les autres ici - y compris la mienne. Toutes les autres réponses dépendent du shell citant d'une manière ou d'une autre pour gérer tous les cas de bord. Cela ne fonctionne tout simplement pas si bien. Croyez-moi, j'ai ESSAYÉ. Regardez:
AUCUNE quantité de caractères géniaux ou de guillemets contenus ne peut casser cela car les octets de chaque valeur ne sont évalués qu'au moment même où le contenu est recherché. Et nous savons déjà que cela a fonctionné comme valeur au moins une fois - il n'y a pas de protection d'analyse ou de citation nécessaire ici car il s'agit d'une copie octet par octet de la valeur d'origine.
La fonction évalue d'abord les
$var
noms et attend que les vérifications soient terminées avant de se.dot
procurer le here-doc qui l'a alimenté sur le descripteur de fichier 3. Avant de le rechercher, c'est à quoi il ressemble. C'est infaillible. Et POSIX portable. Eh bien, au moins la gestion \ 0null est POSIX portable - le système de fichiers / process est évidemment spécifique à Linux. Et c'est pourquoi il y a deux fonctions.la source
Utilisation
source
et substitution de processus :Prochainement:
Utilisation
eval
et substitution de commandes :L'
sed
appel peut être remplacé par unawk
appel:Mais n'oubliez pas qu'il n'efface pas les variables d'environnement qui ne sont pas dans le pid 1.
la source
Il convient de noter que les processus peuvent avoir des variables d'environnement qui ne sont pas des variables Bash / Sh / * sh valides - POSIX recommande mais n'exige pas que les variables d'environnement aient des noms correspondant
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.Pour générer une liste de variables compatibles avec le shell à partir d'un autre environnement de processus, dans Bash:
De même, pour les charger:
Ce problème ne survient qu'occasionnellement mais quand il le fait ...
la source
Je pense que c'est POSIX portable:
Mais @Gilles fait un bon point -
sed
gérera probablement les valeurs nulles, mais peut-être pas. Donc, il y a cette méthode portable POSIX (je pense vraiment cette fois) :Pourtant, si vous avez GNU, il
sed
vous suffit de faire:Eh bien, POSIX portable, à l'exception de celui
/dev/...
qui n'est pas spécifié, mais vous pouvez vous attendre à ce que cette syntaxe se comporte de la même manière sur la plupart des Unices.Maintenant, si cela a quelque chose à voir avec votre autre question , vous pouvez l'utiliser comme ceci:
Le document ici est extrêmement utile en ce qu'il empêche le shell de visser avec l'une des citations que nous travaillons si dur à gérer dans le sous-shell et nous fournit également un chemin fiable vers un fichier
.dot
source plutôt que, encore une fois, un sous-shell ou un shell variable. D'autres ici utilisent le bashisme qui fonctionne à peu près de la même manière - seulement c'est définitivement un anonyme alors que POSIX ne spécifie qu'un pour ici-docs et il peut donc s'agir de n'importe quel type de fichier, bien qu'en pratique, c'est généralement un fichier. ( en revanche, utilise l'anonymat pour here-docs) . La chose malheureuse à propos de la substitution de processus, cependant, est également dépendante du shell - ce qui pourrait être un problème particulièrement ennuyeux si vous travaillez avec .<(process substitution)
|pipe
iohere
temp
dash,
|pipes
init
Cela fonctionne également avec
|pipes
bien sûr, mais vous perdez à nouveau l'environnement à la fin lorsque l'|pipe's
état s'évapore avec sa sous-couche. Là encore, cela fonctionne:le
sed
instruction elle-même fonctionne en maintenant chaque ligne en mémoire jusqu'à ce qu'elle atteigne la dernière, date à laquelle elle effectue un remplacement global en gérant les citations et en insérant des sauts de ligne le cas échéant en ancrant sur les valeurs nulles. Assez simple vraiment.Dans l'
dash
image, vous verrez que j'ai choisi d'éviter le \ mess et ajouté l' optionGNU
spécifique-r
àsed
. Mais c'est juste parce que c'était moins à taper. Cela fonctionne de toute façon, comme vous pouvez le voir dans lezsh
image.Voici
zsh
:Et voici
dash
faire la même chose:Même les échappées terminales sont indemnes:
la source
/proc/PID/environ
. La question est donc de savoir ce que Solaris sed prend en charge - ou si Solaris l'a/proc/PID/environ
, il ne l'a pas utilisé, mais je suis bien derrière la courbe des fonctionnalités de Solaris, ce qui pourrait se produire de nos jours.)sed
est requis pour gérer l'ascii hexadécimal, dont l'octet nul est un. En plus, je me suis juste demandé si c'était encore plus facile de faire ça.\xNN
syntaxe n'est pas requise dans POSIX, pas même la\OOO
syntaxe octale (dans les chaînes C et dans awk, oui, mais pas dans les expressions rationnelles sed)./proc/PID/environ
après tout (il contient plusieurs autres entrées de type Linux/proc/PID
, mais pasenviron
). Une solution portable n'a donc pas besoin d'aller au-delà des outils Linux après tout, c'est-à-dire GNU sed ou BusyBox sed. Les deux prennent en charge\x00
dans une expression régulière, donc votre code est aussi portable que nécessaire (mais pas POSIX). C'est cependant trop complexe.la source