web-dev-qa-db-fra.com

Prendre le nom d'utilisateur en entrée: si l'utilisateur est connecté, afficher les processus en cours appartenant à l'utilisateur

Je veux écrire un script qui prend le nom d'un utilisateur en tant qu'entrée de ligne de commande. Si cet utilisateur est connecté, il affichera les processus qu'il exécute. S'il n'est pas connecté, le script doit le mentionner.

Ma tentative ne fonctionne pas:

#!/bin/bash
echo "Who are you?"
read user
echo $user
name=$(whoami)
if[$user == $name]
then
  top -u $user
else
  echo "not logged in"
fi
2
rumana khanom

Vous pouvez utiliser la commande who -u pour répertorier les utilisateurs connectés. Vous pouvez également utiliser grep pour rechercher un utilisateur spécifique dans la sortie et quitter avec succès s'il est trouvé ou quitter en cas d'échec sinon .

#!/bin/bash

read -p 'Enter username to check: ' user
if who -u | grep -q "^$user "; then
    top -u "$user"
else
    echo "User $user is not logged in"
fi

(Merci à @dessert pour avoir raccourci la partie who -u | ...!)

3
janos

Ce que vous demandez peut être fait avec un oneliner:

read -p"Who are you? " u&&((who -u|grep -q "^$u "&&top -u"$u")||echo "$u is not logged in")

Mais comme vous avez demandé un script, voici la version de script beaucoup plus agréable:

#!/bin/bash
read -p "Who are you? " user && ((    # Prompt for username, save as $user
who -u | grep -q "^$user "   &&       # test if user is logged in
top -u "$user"                   ) || # run top with that username
echo "$user is not logged in"   )     # error message

Des explications

  • read -p "Who are you? " user - Demander le nom d'utilisateur et l'enregistrer en tant que variable user
  • && - si cela réussit,…
  • (…) - commencez un sous-shell et faites dedans - si vous ne voulez pas démarrer un sous-shell, vous pouvez utiliser { …;} à la place, l'espace ainsi que le point-virgule sont obligatoires
  • who -u | grep -q "^$user " - appelle who et grep pour le nom d'utilisateur situé au début de la ligne (^) avec un espace précédent (de sorte que des ne correspond pas dessert)
  • top -u "$user" - marche en haut avec le nom d'utilisateur
  • || - si c'est pas réussi, c'est-à-dire si l'utilisateur n'est pas connecté
  • echo "$u is not logged in" - message d'erreur d'impression

NB: Ceci peut très bien être aussi fait avec une expression if comme indiqué dans les autres réponses. Je me suis tenu aux opérateurs logiques et aux crochets car c’était une autre façon de procéder et je voulais montrer comment.

3
dessert

Il me semble que vous avez un peu mal compris la tâche. Je suppose que le script est quelque chose qu'un administrateur système utiliserait pour vérifier les utilisateurs, donc "Qui êtes-vous?", Et vérifier que l'utilisateur qui exécute le script a entré son propre nom d'utilisateur (ce que votre script essaie de faire) n'est pas ce que vous sont censés faire!

Je pense que réponse de janos et réponse de dessert faites exactement ce que vous voulez, et je n'ai pas de meilleure réponse. Mais voici quelques astuces pour déboguer votre script ...

test aussi appelé [

Vous avez utilisé [ qui est un shell intégré. Vous pouvez voir des informations à ce sujet en exécutant help [, mais comme cette information l’indique, il s’agit d’une version de la commande test et vous trouverez plus d’informations sous help test. Lorsque j'exécute votre script (que j'ai nommé script), j'obtiens ces erreurs:

script: line 6: if[zanna == zanna]: command not found
script: line 7: syntax error near unexpected token `then'
script: line 7: `then'

vous avez besoin de trois espaces pour séparer les commandes if et [ de leurs arguments. En outre, comme l'a fait remarquer Sergiy dans un commentaire, jusqu'à la version 4.4 de Bash , l'opérateur == n'existait pas dans test ou [. Ubuntu 16.04 utilise Bash 4.3. J'ai Bash 4.4 dans 17.10. Vous pouvez corriger l'erreur de syntaxe comme ceci:

if [ "$user" = "$name" ]

Vous auriez également pu éviter d’affecter une variable supplémentaire en effectuant ce test.

if [ "$user" = "$(whoami)" ]

mais la brièveté n’apporte pas toujours des éclaircissements, en particulier dans les scripts Shell, et d’ailleurs, , ce n’est pas ce que vous voulez vraiment faire , car Le script doit être connecté pour exécuter un script. Ainsi, même la version syntaxiquement correcte de votre script vérifierait uniquement que l'utilisateur a correctement saisi son nom d'utilisateur, ce qui n'est pas ce que la tâche demande.

read

read est une commande intégrée de Bash. Vous pouvez obtenir des informations à ce sujet en exécutant help read.

Lorsque vous utilisez la commande read, vous souhaiterez probablement utiliser l'option -r pour empêcher les barres obliques inverses de l'entrée d'agir en tant que sorties d'échappement.

De plus, plutôt que echoing l'invite utilisateur, vous pouvez utiliser l'option -p de read et écrire l'instruction Invite après -p pour un script plus concis.

echo "Who are we checking on? "
read -r user

fait la même chose que

read -rp "Who are we checking on? " user

De plus, vous n'avez pas strictement besoin de nommer la variable, car read place automatiquement l'entrée dans une variable REPLY. Vous pouvez tester ceci:

read -rp "Who are we checking on? "
echo "$REPLY"

Bien sûr, vous voulez souvent nommer la variable. Je pense que user était un bon choix pour celui-ci.

if

if est également un shell intégré, vous pouvez donc le découvrir en exécutant help if. Vous verrez qu'il vérifie la commande après celle-ci et exécute la branche then si l'état de sortie de cette commande était égal à zéro (c'est-à-dire qu'il a abouti). réponse de janos utilise if sans test ou [ en collectant simplement le statut de sortie de grep:

who -u | grep -q "^$user "

recherche dans la sortie de who -u pour voir si une ligne commence par la valeur de la variable $user. ^ est le début de la ligne et l'option -q supprime la sortie. L'état de sortie de grep est zéro s'il trouve une correspondance. Par conséquent, si $user est trouvé, la branche then de la structure if sera exécutée, mais si grep _ ne trouve rien, la branche else de la structure if sera exécutée (si elle existe).

réponse du dessert utilise uniquement la logique du shell pour définir les actions en cas de succès ou d'échec d'une commande - même if n'est pas nécessaire ici :)

test encore

Puisque le contrôle du statut de sortie suffit, je ne pense pas que vous ayez besoin de la commande [ ou test. Si vous voulez vraiment l'utiliser, vous pouvez utiliser quelque chose comme

[ -n "$(w -h | grep "^$user ")" ]

Toute la substitution de commande doit être citée ou [ se plaindra de trop d'arguments s'il y a plusieurs mots dans la sortie (puisque $user sera un mot, nous pourrions également utiliser grep -o pour afficher seulement le match). -n est vrai si la chaîne n'est pas vide.

Une alternative à who -u est w -h. Je ne sais pas ce qui est le plus portable ou le plus fiable. J'ai remarqué que who donne une sortie légèrement différente dans différents émulateurs de terminal, bien que cela ne soit pas assez différent pour empêcher ce script de fonctionner.

Citant

La plupart du temps, vous souhaitez citer des variables dans des scripts pour empêcher toute expansion ultérieure. Les utilitaires que vous utilisez pour créer des utilisateurs sur Ubuntu ne vous permettront pas de créer un nom d'utilisateur avec des espaces ou tout autre caractère pouvant entraîner l'expansion du shell. Je ne pense donc pas qu'il soit absolument essentiel de citer la variable dans ce script. Néanmoins, il est possible que de tels noms d'utilisateur existent, et c'est une bonne habitude de citer des variables qu'il n'est pas nécessaire de ne pas citer.


Pour être complet, voici ma version sans [ (c'est essentiellement la même chose que janos '):

#!/bin/bash

read -rp "Who are we checking on? "
if w -h | grep -q "^$REPLY "; then
    echo "here's what "$REPLY" is doing:"
    top -u "$REPLY"
else
    echo "looks like "$REPLY" is not logged in."
fi
3
Zanna