7
votes

Comment puis-je savoir quel script, programme ou quel shell a exécuté mon script Perl?

Comment puis-je déterminer quel script, programme ou shell a exécuté mon script Perl?

Exemple: Je souhaiterais peut-être avoir une sortie lisible à l'homme si elle est exécutée de Shell (personnalisée pour chaque type de shell), un type de sortie différent si appelé comme un script à partir d'un autre script Perl et un format lisible à la machine si elle est exécutée à partir d'une programme tel qu'un serveur d'intégration continue.

Motivation: J'ai un outil qui change sa sortie sur la base de laquelle Shell l'exécute. J'étais normalement implémenter ce comportement en option pour le script, mais la conception de cet outil ne permet pas d'options. D'autres coquilles ont des variables d'environnement qui indiquent ce que Shell est en cours d'exécution. Je travaille sur un correctif pour soutenir PowerShell, qui n'a pas de variable spéciale de ce type.

Edit: Beaucoup de ces réponses sont spécifiques à Linux. Malheureusement, PowerShell est pour Windows. getppid , le $V {shell} variable et shelling to ps ne vous aidera pas dans ce cas. Ce script doit exécuter une plate-forme croisée.


7 commentaires

Je ne suis pas sûr de comprendre - ne devriez-vous pas regarder le processus parent dans ce cas?


Vous pouvez tester pour voir si stdout est un terminal ( -t ) et, dans l'affirmative, supposons que vous avez été invoqué à partir d'une coque interactive plutôt que d'un démon d'intégration continue. Cependant, cette technique commune ne parle pas de personnaliser la production par parent distincte - possible (mais je pense que c'est un peu de désir égaré, de toute façon).


Oublié de mentionner, normalement, il cherche une variable d'environnement que la coquille ou l'utilisateur définit pour indiquer ce que Shell est en cours d'exécution; Avec PowerShell, il n'y a pas de variable d'environnement de ce type.


@ X0N: Oui, dans un * Nix Seul World, getppid ferait des merveilles. Ce script doit fonctionner sur Windows, spécifiquement, avec PowerShell et Getppid n'est pas implémenté dans la fraise Perl ou Activeest Perl.


@ROBERTP J'ai compris un piratage pour détecter PowerShell 2 ou plus. Voir la réponse ci-dessous. Mise à jour - Oh, quelqu'un d'autre m'a battu. Supprimer ma réponse.


BTW, lorsque vous détectez PowerShell, vous pouvez émettre du texte CLIXML-Serialized et PowerShell désoriendront automatiquement le texte dans des objets. cool, hein?


PowerShell est en effet très soigné. :)


5 Réponses :


1
votes

Selon votre environnement, vous pourrez peut-être récupérer les variables d'environnement. Considérez le code suivant:

      '_' => '/bin/sh',
      'SHELL' => '/bin/bash',


4 commentaires

Ah, a finalement compris pourquoi j'ai été évité. N'a pas vu la balise PowerShell jusqu'à maintenant. Ma faute.


N'était-ce pas moi qui vous a baissé, mais j'adorerais pour une variable d'environnement de me dire PowerShell. Malheureusement, PowerShell n'a pas une telle variable. Le script utilise l'environnement pour déterminer quoi générer pour d'autres types de shell.


Regardant ici vlaurie.com/computers2/articles/... Il ressemble à des points Comspec à cmd.exe par défaut; Peut-être que cela pointe sur l'exécutable PowerShell lorsqu'il est exécuté sous PowerShell? Si tel est le cas, vous devriez pouvoir comprendre l'environnement d'exécution de l'environnement, y compris Cygwin et similaires ...


Je souhaite :-) Malheureusement, PowerShell ne change pas cette variable. J'ai fait une comparaison complète entre PowerShell et l'invite de commande traditionnelle dans Windows et la seule indication que vous n'êtes pas dans cette invite de commande est qu'il manque la variable «Invite»! Pas l'indicateur le plus fiable. :)



5
votes

Vous utilisez getppid () . Prenez cet extrait dans enfant.pl : xxx

si vous l'exécutez à partir de la ligne de commande, système affichera bash < / code> ou similaire (entre autres). Exécuter avec Système ("perl enfant.pl"); dans un autre script, par exemple parent.pl , et vous verrez que perl parent.pl l'exécutore.

pour capturer juste le nom du processus avec des arguments (grâce à ikegami pour le correct ps syntaxe): xxx

edit: une alternative à cette approche, pourrait être de créer doux Liens vers votre script, apportez les différents contextes d'utiliser différents liens pour accéder à votre script et inspecter 0 $ pour créer la logique autour de cela.


9 commentaires

Un peu plus fiable: chomp (My $ PARENT_NAME = `PS -NO-Headers -O cmd $ ppid`);


@ikegami: merci. :) Je ne savais pas comment faire spécifier ce format.


Malheureusement, Perl sur Windows ne prend pas en charge getppid () ni shelling to ps une possibilité. :(


Robert P, ce que vous dites n'est pas strictement vrai, cela dépend. Avec Cygwin, la plupart d'entre elles fonctionnent réellement (au moins la partie de la bombardement, que j'utilise déjà dans un projet).


@Mariuskjeldahl - Il y a une balise PowerShell à cette question.


OK, laissez-moi reformuler: la fraise et l'activation de Perl sous Windows ne mettent pas en œuvre getppid :)


@Mariuskjeldahl - Que dites-vous? Lisez la question. OP dit qu'ils travaillent sur un patch pour PowerShell.


@Marius: PowerShell est une coquille. Il se trouve que c'est une coquille pour Windows.


J'ai répondu à un commentaire de Robert P qui indique quelque chose à propos de Perl sur Windows qui n'est pas vrai. C'est un commentaire pertinent dans ce contexte. Mais la pédantique peut aussi être amusante, c'est pourquoi j'ai rejoint la fête. Laissez-le reposer déjà.



3
votes

Je suggérerais une approche différente pour atteindre votre objectif. Au lieu de deviner dans le contexte, rendez-la plus explicite. Chaque cas d'utilisation est totalement séparé, alors trois interfaces différentes.

  1. Une fonction pouvant être appelée dans un programme PERL. Cela rendrait probablement une structure de données PERL. Ceci est beaucoup plus facile, plus rapide et plus fiable que la sortie de script d'analyse. Cela servirait également de base aux scripts.

  2. Un script qui sortira pour la coque actuelle. Il peut regarder $ env. {Shell} pour découvrir ce que Shell est en cours d'exécution. Pour des points bonus, fournissez un commutateur pour remplacer explicitement.

  3. Un script pouvant être appelé à l'intérieur d'un programme non-Perl, tel que votre serveur d'intégration continue et émettre une sortie lisible par machine. XML et / ou JSON ou autre.

    2 et 3 ne seraient que des wrappers minces pour formater les données sur 1.

    Chacun est adapté à son besoin spécifique. Chacun travaillera sans heuristique. Chacun sera beaucoup plus simple que d'essayer de deviner le contexte et de ce que l'utilisateur veut.

    Si vous ne pouvez pas séparer 2 et 3, demandez au serveur d'intégration continue définir une variable d'environnement et recherchez-la.


1 commentaires

Convenu, dans le cas général. Comme je l'ai mentionné, les éléments ci-dessus n'étaient que des exemples d'applications possibles de cette technique. Dans ce cas, le script émet un script shell et d'autres outils s'attendent à ce que la bonne sorte de script shell pour la coquille invoque le script. Pour presque tous les autres coquilles, il existe des variables d'environnement qui indiquent la coquille à utiliser. PowerShell ne donne pas une telle variable.



1
votes

Ceci est sur Windows XP avec PowerShell V2.0, alors prenez-la avec un grain de sel.

dans un cmd.exe shell, je reçois:

psmodulepath = c: \ windows \ system32 \ windowspowershell \ v1.0 \ modules \

tandis que dans la fenêtre de la console PowerShell, je reçois:

Psmodulepath = E: \ home \ utilisateur \ windowspowershell \ modules; c: \ windows \ system32 \ windowsp owershell \ v1.0 \ modules \

E: \ home \ utilisateur est l'endroit où mon dossier "My Documents" est. Donc, une heuristique peut être de vérifier si psmodulepath contient un chemin de dépendant de l'utilisateur.

De plus, dans une fenêtre de console, je reçois:

! :: = :: \

dans l'environnement. Du PowerShell Ise, je reçois: xxx


1 commentaires

+1 - Ah, merde. Je n'ai même pas remarqué votre réponse. Je viens de comprendre la même chose. Au fait, ce n'est pas PowerShell 1.0 - V1 ne prend pas en charge les modules. Le chemin sous% Windir% est V1.0 pour V1, V2 et V3 de PowerShell.



1
votes

Si vous exécutez PowerShell 2.0 ou plus (probablement), vous pouvez déduire la coque en tant que processus parent en examinant la variable d'environnement % psmodulepath% . Par défaut, il pointe des modules système sous % windir% \ system32 \ windowspowershell \ v1.0 \ modules ; C'est ce que vous verrez si vous examinez la variable de cmd.exe .

Toutefois, lorsque PowerShell démarre, il réduit le chemin de recherche du module par défaut de l'utilisateur à cette variable d'environnement qui ressemble à: % userprofile% \ documents \ windowspowershell \ modules . Ceci est hérité des processus d'enfants. Donc, votre logique serait de tester si% PSModulePath% commence par% UserProfile%% pour détecter PowerShell 2.0 ou plus. Cela ne fonctionnera pas dans PowerShell 1.0 car il ne prend pas en charge les modules.


0 commentaires