Looping através de um array de shell dado como parâmetro

3

Estou tentando escrever um pequeno script auxiliar que alterará as permissões e a propriedade de alguns sites em um servidor.

Neste momento, posso passar em um site ou fazer tudo simplesmente ignorando esse argumento.

O que eu estou descobrindo é que eu preciso ser capaz de aplicar a vários sites no servidor, mas não todos, então tentei fazer uma tentativa de passar um array via:

SLIST=("my.site.com" "your.site.com")
./website-perms 644 755 kevin "${SLIST[@]}"

No entanto, ele só faz o primeiro item na matriz my.site.com

Como corrijo isso para poder transmitir uma matriz de sites?

CÓDIGO COMPLETO

#!/bin/bash

# Done nightly, and copied to /usr/bin/
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi
if [ $# -eq 0 ]; then
    echo "usage: ./website-perms.sh fileperm folderperm owner (1|2) (1=kevin,2=www-data) (optional) Site Array"
    exit 1
fi

function chg_perms() {
    echo "find $1 -type f -exec chmod $2 {} \";
    echo "find $1 -type d -exec chmod $3 {} \";
    find $1 -type f -exec chmod $2 {} \;
    find $1 -type d -exec chmod $3 {} \;
    echo "-- chg_perms done";
}

function chg_owner() {
    echo "chown -R $2:www-data $1";
    chown -R $2:www-data $1;
    echo "-- chg_owner done";
}

SITES=$4;
if [ -z $SITES ]; then
    for dir in /var/www/httpdocs/*/
    do
        dir=${dir%*/}
        chg_perms "/var/www/httpdocs/${dir##*/}" $1 $2
        chg_owner "/var/www/httpdocs/${dir##*/}" $3
    done;
else
    for dir in "${SITES[@]}" #ONLY DOES THE FIRST ITEM
    do
        chg_perms "/var/www/httpdocs/$dir" $1 $2
        chg_owner "/var/www/httpdocs/$dir" $3
    done
fi;
    
por Kevin 30.11.2015 / 21:50

2 respostas

8

Bom roteiro. Normalmente eu usaria todos os argumentos restantes como a lista de sites. Algo parecido com isto (eu não testei estes mods):

if [ $# -lt 3 ]; then
    echo >&2 "usage: $0 fileperm folderperm owner [site ...]"
    exit 1
fi

[. . . ]

fileperm="$1"
folderperm="$2"
owner="$3"
shift 3             # shift first 3 args off of list

if [ $# -eq 0 ]; then
    for dir in /var/www/httpdocs/*/    #stackexchange syntax coloring fix*/
    do
        dir="${dir%/*}"
        chg_perms "/var/www/httpdocs/${dir##*/}" "$fileperm" "$folderperm"
        chg_owner "/var/www/httpdocs/${dir##*/}" "$owner"
    done;
else
    for dir           # step through positional args ($1,$2,...,$N)
    do
        chg_perms "/var/www/httpdocs/$dir" "$fileperm" "$folderperm"
        chg_owner "/var/www/httpdocs/$dir" "$owner"
    done
fi
    
por 30.11.2015 / 22:02
4

Uma tomada ligeiramente diferente, embora eu prefira a abordagem de RobertL

sites=( "${@:4}" )
# ...
for dir in "${sites[@]}"; do ...
  • Para declarar uma matriz, você deve usar parênteses.
  • "${@:4}" aceita os parâmetros posicionais, a partir de $ 4 até o final.
  • saia do hábito de usar ALLCAPSVARNAMES: deixe-os restritos apenas ao uso do shell.
por 30.11.2015 / 22:30