Usando uma função definida em um script pai

1

Eu escrevi o seguinte script no test.sh:

#!/bin/sh
compare() { 
if [ $1 != root ]; then 
echo "Fail" >> CAT1.txt 
fi 
}
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c 'compare "$@"' _

quando executo este script, recebo o seguinte erro:

_: compare: command not found
    
por Gohar 07.07.2015 / 10:18

3 respostas

2

Uma função é interna ao shell que a define. Se você executar outro programa, esse outro programa não verá a função, mesmo que também seja um shell.

(As funções são acessíveis em subshells, ou seja, quando uma cópia do shell em execução é executada para executar algo entre parênteses (…) ou para uma substituição de comando $(…) etc. Mas eles não são acessíveis em programas separados, por exemplo, quando execute sh -c … .)

Defina a função no script que a usa:

#!/bin/sh
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c '
  compare() { 
  if [ $1 != root ]; then 
  echo "Fail" >> CAT1.txt 
  fi 
  }
  compare "$@"' _

(Eu suponho que este é um exemplo de brinquedo, tudo isso pode ser feito em um único script awk simples.)

Como alternativa, você pode usar um recurso bash que permite que as funções sejam exportadas através do ambiente para uma instância filha do bash. Este é um recurso específico do bash, então o script pai teria que executar o bash, não sh.

#!/bin/bash
compare() { 
if [ $1 != root ]; then 
echo "Fail" >> CAT1.txt 
fi 
}
export -f compare
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c 'compare "$@"' _
    
por 08.07.2015 / 03:25
0
  1. por que não usar ...?

    awk -F: '$4==0 && $1 != root ' /etc/passwd > CAT1.txt
    

    1.1 editar obter falha

    awk -F: '$4==0 && $1 != root {print "Fail" ; } /etc/passwd > CAT1.txt
    

    para obter falha E nome de usuário

    awk -F: '$4==0 && $1 != root {printf "Fail %s\n",$1 ; } /etc/passwd > CAT1.txt
    
  2. A definição da função
  3. é perdida ao se bifurcar o novo bash. Ae @mueh disse, você precisa export -f compare .

por 07.07.2015 / 10:28
0

Você deve fazer isso com uma lógica de bifurcação de algum tipo. Defina um marcador no ambiente do seu script que definitivamente provará às instâncias filho do seu script que elas devem fazer uma coisa enquanto o pai faz outra. Dessa forma, você pode tornar o script recursivo com segurança.

#!/bin/sh
case $Z:$P in 
("$0:${1:-!$P}")
     [ root = "$2" ] ||
     ! echo Fail
;;(*)
     set -a; Z=$0 P=$$
     </etc/passwd     \
     awk -F: '$4 == 0'|
     cut -d: -f1      |
     xargs -n1 "$0" "$$"
esac >>CAT1.txt

Ou, talvez use seus fds para fazer o teste. Se você está executando o script em primeiro lugar a partir de um terminal, então ...

#!/bin/sh
[ -t 0 ] && {
     awk '$4 == 0' |
     cut   -d: -f1 |
     xargs -n1 "$0"
     exit
} </etc/passwd >>CAT1.txt
[ root = "$1" ]   ||
! echo Fail

Mas a melhor maneira é alterar o $0 :

da criança
#!/bin/sh
[ . = "$0" ] && {
    [ root = "$1" ] ||
    ! echo Fail
}
z=$(head -n5 <"$0")
</etc/passwd  \
awk '$4 == 0' |
cut -d:  -f1  |
>>CAT1.txt    \
xargs -n1     \ 
sh -c "$z" . 
    
por 08.07.2015 / 06:23