Enquanto script Bash de loop que gera quantos usuários usam um determinado shell

0

Então eu estou preso ao tentar criar um script bash enquanto a função loop pega a entrada de / etc / passwd e mostra quantos usuários usam bash, nolongin, csh e ksh. Eu acredito que devo usar o gato e cortar. E eu sei que o tipo de shell que um usuário usa está no sétimo campo.

Estou correto em pensar que eu deveria criar uma variável para cada tipo de shell e incrementá-lo toda vez que ele encontrar um usuário que use aquele shell em particular?

Até agora, esse é o código que tenho mas, por algum motivo, ele só gera a declaração final if.

declare -i bash;
declare -i nologin;
declare -i csh;
declare -i ksh;

bash=0;
nologin=0;
csh=0;
ksh=0;
cat /etc/passwd | cut -d: -f7 $line | while read line;
do
    if [ $line == "bash" ]
            then
                    bash=bash+1;
    else  fi [ $line == "/sbin/nologin" ]
            then
                    nologin=nologin+1;
    else fi [ $line == "chs" ]
            then
                    chs=chs+1;
    else
            then
                    ksh=ksh+1;
    fi
done

Atualização: Até agora mudei o código e atualizei o que tenho. Ele percorre e distribui a parte correta da instrução if, mas estou tendo problemas para tentar incrementar as variáveis que possuo.

    
por DoctorWho22 09.04.2015 / 00:32

4 respostas

1

Aqui está minha versão:

#!/bin/bash

bash=0;
nologin=0;
csh=0;
ksh=0;

while read line;
do
    innerline=$(echo "$line"| cut -d: -f7)

    if [[ $innerline == "/bin/bash" ]]
    then
                    bash=$(echo "$bash+1"|bc);
    elif [[ $innerline == "/sbin/nologin" ]]
    then
                    nologin=&(echo "$nologin+1"|bc);
    elif [[ $innerline == "/bin/csh" ]]
    then
                    csh=$(echo "$csh+1"|bc);
    else
                    ksh=$(echo "$ksh+1"|bc);
    fi
done < /etc/passwd

echo "$bash $nologin $csh $ksh"

Para incrementar os valores, passo o trabalho de cálculo para bc , que é um pequeno utilitário de cálculo.

Deixe-me saber se funciona para você.

Para ser honesto, devo dizer que realmente não gosto dessa solução. Embora o loop seja desnecessário e prefiro a solução @Nat, no entanto, como você afirmou claramente que o loop deve estar presente - aqui está.

PS. Esta é apenas uma ideia terrível:

else
                        ksh=$(echo "$ksh+1"|bc);

para assumir que todo shell desconhecido / sem correspondência é ksh .

    
por 09.04.2015 / 10:59
3

Eu não tenho certeza se isso é lição de casa, então isso pode não se encaixar nos seus requisitos, mas você não precisa realmente de um script inteiro para fazer isso. Isso pode ser feito com um one-liner.

cat /etc/passwd | cut -d ':' -f 7 | sort | uniq -c

Veja como a saída é

  4 /bin/bash
  6 /sbin/nologin
  4 /usr/bin/csh
 13 /usr/bin/ksh

Como isso funciona é que uniq(1) "Filtros adjacentes linhas de correspondência do INPUT" e com a opção -c contará linhas adjacentes, e é por isso que precisamos classificar as linhas primeiro que todas as linhas correspondentes serão adjacentes.

    
por 09.04.2015 / 05:48
0

Alguns ensinaram

 cat /etc/passwd | while read line;

colocará na linha

 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash

então,

  cut -d: -f7 $line == "bash"

avaliará

 cut -d: -f7 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash == "bash"

cut irá procurar nos 3 arquivos tmpfoo: x: 1004: 1005: utilisateur, test e sudo: / home / tmpfoo: / bin / bash que provavelmente não é o que você quer.

como presente, experimente este loop de amostra

cat /etc/passwd |  cut -d: -f7 | while read line;
do
    echo $line
done
    
por 09.04.2015 / 10:33
0

I believe I am supposed to use cat and cut.

It is something I am working on for a Unix class so I am supposed to create a while loop function.

Naturalmente, os arquivos em que os registros são de comprimento variável delimitados por novas linhas e os campos são delimitados por um único caractere delimitador, como o arquivo de senhas do UNIX Versão 7, são coisas em que awk se destaca. Então, para o benefício das pessoas que estão vindo para cá sem as restrições acima, aqui está o awk one-liner:

awk -F : '{x[$7]++;} END {for (k in x) print k": "x[k]}' /etc/passwd

As lições para aprender aqui são:

  • O UNIX possui ferramentas especializadas adaptadas aos seus formatos de arquivo de banco de dados históricos. Esse tipo específico de formato de arquivo é fácil de usar em awk .
  • Você não precisa usar cat , apesar do que os instrutores possam dizer. ☺ Existe um excesso de pipelines de comando. No caso do loop while , o redirecionamento simples funcionará, como na resposta do mnmnc. No caso de awk , os arquivos a serem processados são simplesmente fornecidos como argumentos.
  • O loop while aqui está, é claro, dentro do programa awk . Sua função principal é ler e processar sequencialmente todos os registros em seu (s) arquivo (s) de entrada, o que faz com um loop.
  • Am I correct in thinking that I should create a variable for each type of shell and increment it each time it finds a user that uses that particular shell?
    Sim, e o awk one-liner aqui usa o que é chamado de array associativo , a variável x . A segunda parte do script awk mostra a maneira usual de iterar o conteúdo de um array associativo. A primeira parte é simplesmente um incremento (o ++ postfix operator) do valor de um elemento na matriz, indexado pelo campo sete do registro (que awk disponibiliza como $7 ).

    Note que você também pode fazer matrizes associativas em shell scripts do Bourne Again e adaptar esta técnica para o script para a resposta restrita. Você pode estar limitado a usar um while loop; mas ninguém o limitou a usar if declarações .

Leitura adicional

por 09.04.2015 / 12:27