[successivo]
[precedente]
[inizio]
[fine]
[indice generale]
[indice ridotto]
[indice analitico]
[volume]
[parte]
Capitolo 165. Raccolta di funzioni per una shell POSIX
In questo capitolo viene proposta una raccolta di funzioni per una shell POSIX comune, allo scopo di facilitare la gestione di un sistema GNU/Linux. Queste funzioni derivano dall'esperienza di nLnx (una distribuzione GNU/Linux per architettura x86, derivata da Debian, descritta nel volume XXXIV).
Queste funzioni si avvalgono evidentemente di programmi di servizio comuni nei sistemi Unix; in particolare SED (capitolo 688). Evidentemente, la comprensione del funzionamento di queste funzioni richiede una buona conoscenza nell'uso di tali programmi.
165.1
Estrapola da «/etc/passwd» le righe di un certo intervallo di numeri UID
password_records_by_uid_range uid_min uid_max < /etc/passwd > output_file
|
passwd_records_by_uid_range () {
local UID_MIN="$1"
local UID_MAX="$2"
local RECORD=""
local USER_ID=""
#
while read -r RECORD
do
USER_ID=`echo $RECORD | sed "s/^[^:]*:[^:]*:\([0-9]*\):.*/\1/"`
#
if [ 0$USER_ID -ge $UID_MIN ] && [ 0$USER_ID -le $UID_MAX ]
then
echo $RECORD
fi
done
}
|
|
L'esempio seguente utilizza la funzione per estrapolare le righe di /etc/passwd associate a numeri UID tra 1 000 e 29 999. Il risultato viene emesso semplicemente attraverso lo standard output.
cat /etc/passwd | passwd_records_by_uid_range 1000 29999
|
|
165.2
Estrapola da «/etc/passwd» le righe di un certo intervallo di numeri GID
password_records_by_gid_range gid_min gid_max < /etc/passwd > output_file
|
passwd_records_by_gid_range () {
local GID_MIN="$1"
local GID_MAX="$2"
local RECORD=""
local GROUP_ID=""
#
while read -r RECORD
do
GROUP_ID=`echo $RECORD | sed "s/^[^:]*:[^:]*:[^:]*:\([0-9]*\):.*/\1/"`
#
if [ 0$GROUP_ID -ge $GID_MIN ] && [ 0$GROUP_ID -le $GID_MAX ]
then
echo $RECORD
fi
done
}
|
|
L'esempio seguente utilizza la funzione per estrapolare le righe di /etc/passwd associate al numero GID zero.
cat /etc/passwd | passwd_records_by_gid_range 0 0
|
|
165.3
Estrapola da «/etc/group» le righe di un certo intervallo di numeri GID
group_records_by_gid_range gid_min gid_max < /etc/group > output_file
|
group_records_by_gid_range () {
local GID_MIN="$1"
local GID_MAX="$2"
local RECORD=""
local GROUP_ID=""
#
while read -r RECORD
do
GROUP_ID=`echo $RECORD | sed "s/^[^:]*:[^:]*:\([0-9]*\):.*/\1/"`
#
if [ 0$GROUP_ID -ge $GID_MIN ] && [ 0$GROUP_ID -le $GID_MAX ]
then
echo $RECORD
fi
done
}
|
|
L'esempio seguente utilizza la funzione per estrapolare le righe di /etc/group associate ai numeri GID da 1 000 a 29 999.
cat /etc/group | group_records_by_gid_range 1000 29999
|
|
165.4
Seleziona un utente interattivamente
Per selezionare interattivamente l'utente si usa Dialog e si preferisce depositare il nome scelto in un file:
select_user uid_min uid_max output_file < /etc/passwd
|
select_user_menu () {
#
local UID_MIN="$1"
local UID_MAX="$2"
local RECORD=""
local USER_ID=""
#
local USER_AND_HOME_LIST=""
#
while read -r RECORD
do
USER_ID=`echo $RECORD | sed "s/^[^:]*:[^:]*:\([0-9]*\):.*/\1/"`
#
if [ 0$USER_ID -ge $UID_MIN ] && [ 0$USER_ID -le $UID_MAX ]
then
echo $RECORD | sed "s/^\(.*\):.*:.*:.*:.*:\(.*\):.*/\1 \2/g"
fi
done
}
|
|
select_user () {
#
local UID_MIN="$1"
local UID_MAX="$2"
local INPUT_FILE="$3"
local OUTPUT_FILE="$4"
#
local USER_AND_HOME_LIST=""
local SELECTED_USER=""
#
local TEMPORARY=`tempfile`
echo -n > $TEMPORARY
#
USER_AND_HOME_LIST=`cat $INPUT_FILE \
| select_user_menu $UID_MIN $UID_MAX \
| sort -u`
#
if dialog \
--clear \
--title "Users" \
--menu "Select a user name." \
0 0 0 \
$USER_AND_HOME_LIST \
"!EXIT!" "." \
2> $TEMPORARY
then
SELECTED_USER=`cat $TEMPORARY`
echo "" > $TEMPORARY
#
if [ "$SELECTED_USER" = "!EXIT!" ]
then
SELECTED_USER=""
fi
else
SELECTED_USER=""
fi
#
echo "$SELECTED_USER" > "$OUTPUT_FILE"
rm $TEMPORARY
}
|
|
L'esempio seguente utilizza la funzione per estrapolare un utente dal file /etc/passwd, tra i numeri UID 1 000 e 29 999. Il risultato viene visualizzato attraverso lo standard output.
cat /etc/passwd | select_user 1000 29999 /etc/passwd /tmp/ciao
cat /tmp/ciao
|
|
165.5
Seleziona un campo di una certa riga da un file come «/etc/passwd», «/etc/group» e simili
table_get_column_field file indice n_colonna
|
table_get_column_field () {
#
local INPUT_FILE="$1"
local INDEX="$2"
local COLUMN="$3"
local RECORD=""
local FIELD=""
#
if [ ! -r "$INPUT_FILE" ]
then
echo 1>&2 "[$0] cannot read \"$INPUT_FILE\"."
return
fi
#
if [ "$COLUMN" = "1" ]
then
echo 1>&2 "[$0] index should be more than one."
echo "$INDEX"
return
fi
#
RECORD=`grep -m 1 "^${INDEX}:" "$INPUT_FILE"`
#
if [ "$RECORD" = "" ]
then
echo 1>&2 "[$0] index \"$INDEX\" not found inside \"$INPUT_FILE\"."
return
fi
#
while [ "$COLUMN" -gt "1" ]
do
RECORD=`echo $RECORD | sed "s/^[^:]*://"`
COLUMN=$(($COLUMN - 1))
done
#
FIELD=`echo $RECORD | sed "s/^\([^:]*\).*$/\1/"`
#
echo $FIELD
return
}
|
|
L'esempio seguente utilizza la funzione per estrapolare la parola d'ordine cifrata dell'utente «tizio» dal file /etc/passwd, visualizzando il risultato attraverso lo standard output.
table_get_column_field /etc/shadow tizio 2
|
|
165.6
Aggiunge un utente Unix e Samba, simultaneamente
user_add_unix_samba user passwd home full_name room work_ph home_ph
|
La funzione che viene proposta è estrapolata dallo script nlnxrc di nLnx, dove però viene eseguita un'attività più complessa. Questa edizione particolare non è collaudata ed è qui solo come promemoria.
user_add_unix_samba () {
#
local NEW_USER="$1"
local NEW_PASSWD="$2"
local NEW_HOME="$3"
local NEW_FULL_NAME="$4"
local NEW_ROOM="$5"
local NEW_WORK_PHONE="$6"
local NEW_HOME_PHONE="$7"
local TEMP_USER=""
#
# Elimina le virgole e altri caratteri inopportuni
# dalle informazioni dell'utente.
#
NEW_FULL_NAME=`echo $NEW_FULL_NAME | sed "/,:=/ /g"`
NEW_ROOM=`echo $NEW_ROOM | sed "/,:=/ /g"`
NEW_WORK_PHONE=`echo $NEW_WORK_PHONE | sed "/,:=/ /g"`
NEW_HOME_PHONE=`echo $NEW_HOME_PHONE | sed "/,:=/ /g"`
#
# Verifica che i dati siano validi.
#
if [ "$NEW_USER" = "" ]
then
echo 1>&1 "[$0] cannot create user with no name."
false
return
elif echo "$NEW_USER" | grep "[^a-z0-9]" > "/dev/null"
then
echo 1>&1 "[$0] user name must contain only lower case letters and numbers."
false
return
fi
#
# Il nominativo utente non deve superare i 16 caratteri
#
TEMP_USER=`echo $NEW_USER | sed "s/^\(................\).*$/\1/"`
if [ "$TEMP_USER" = "$NEW_USER" ]
then
true
else
echo 1>&2 "[$0] user name cannot be longer than 16 characters."
false
return
fi
#
# Controlla la directory personale
#
if [ "$NEW_HOME" = "" ]
then
NEW_HOME="/home/$NEW_USER"
fi
#
if [ -e "$NEW_HOME" ]
then
echo 1>&2 "[$0] home directory \"$NEW_HOME\" cannot be created."
false
return
fi
#
# Controlla che ci sia la parola d'ordine.
#
if [ "$NEW_PASSWD" = "" ]
then
echo 1>&2 "[$0] the new user must have a password."
false
return
fi
#
# Crea l'utente, usando inizialmente lo script "adduser",
# secondo le convenzioni Debian.
#
if adduser \
--disabled-password \
--no-create-home \
--home "$NEW_HOME" \
--gecos "$NEW_FULLNAME,$NEW_ROOM,$NEW_WORK_PHONE,$NEW_HOME_PHONE"\
$NEW_USER
then
#
# Crea manualmente la directory personale.
#
mkdir -p "$NEW_HOME"
rmdir "$NEW_HOME"
#
cp -dpR /etc/skel "$NEW_HOME"
chown -R $NEW_USER: "$NEW_HOME"
chmod 0755 "$NEW_HOME"
#
# Aggiunge un collegamento simbolico all'interno di
# "/var/mail/", perché alcuni programmi ne hanno bisogno.
# Si presume che il file "~/mail/mbox" venga usato per
# accumulare i messaggi di posta elettronica dell'utente.
#
rm "/var/mail/$NEW_USER" 2> "/dev/null"
ln -s "../../$NEW_HOME/mail/mbox" "/var/mail/$NEW_USER"
#
# Attribuisce la parola d'ordine (nel farlo, crea anche
# l'utenza per Samba).
#
if user_passwd_unix_samba "$NEW_USER" "$NEW_PASSWD"
then
true
else
#
# Elimina l'utenza.
#
user_del_unix_samba "$NEW_USER"
false
return
else
echo 1>&2 "[$0] cannot create user \"$NEW_USER\"."
false
return
fi
#
rm $TEMPORARY
}
|
|
165.7
Cambia la parola d'ordine a un utente Unix e Samba, simultaneamente
user_passwd_unix_samba user passwd
|
user_passwd_unix_samba () {
#
local OLD_USER="$1"
local NEW_PASSWD="$2"
#
local TEMPORARY=`tempfile`
echo -n > $TEMPORARY
#
# Tenta di eliminare un'utenza vecchia, con lo stesso nome
# dalla gestione di Samba.
#
smbpasswd -x $OLD_USER 2> "/dev/null" 1> "/dev/null"
#
# Imposta la parola d'ordine Unix.
#
if ( sleep 1 ; echo $NEW_PASSWD ; sleep 1 ; echo $NEW_PASSWD ) \
| /usr/bin/passwd $NEW_USER 2> $TEMPORARY
then
#
# Crea o ricrea l'utenza Samba.
#
if [ -x /usr/bin/smbpasswd ]
then
if ( sleep 1 ; echo $NEW_USER ; sleep 1 ; echo $NEW_USER ) \
| /usr/bin/smbpasswd -s -a $NEW_USER 2> $TEMPORARY
then
true
else
echo 1>&2 "[$0] problem changing Samba password to user \
"$NEW_USER": `cat $TEMPORARY`."
rm "$TEMPORARY"
false
return
fi
fi
else
echo 1>&2 "[$0] problem changing Unix password to user \
"$NEW_USER": `cat $TEMPORARY`."
rm "$TEMPORARY"
false
return
fi
rm "$TEMPORARY"
}
|
|
165.8
Elimina un utente Unix e Samba, simultaneamente
user_del_unix_samba () {
#
local OLD_USER="$1"
local OLD_HOME=""
#
# Trova la directory personale.
#
OLD_HOME=`cat /etc/passwd \
| grep "^$OLD_USER:" \
| sed "s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):[^:]*$/\1/"`
#
# Elimina l'utenza dalla gestione di Samba.
#
if [ -x /usr/bin/smbpasswd ]
then
if smbpasswd -x $OLD_USER
then
true
else
echo 1>&2 "[$0] cannot remove Samba user \"$OLD_USER\"."
fi
fi
#
# Elimina l'utenza Unix.
#
if deluser --remove-home "$OLD_USER"
then
#
# Elimina il collegamento simbolico in "/var/mail".
#
rm "/var/mail/$OLD_USER"
else
echo 1>&2 "[$0] cannot remove Unix user \"$OLD_USER\"."
false
return
fi
}
|
|
165.9
Seleziona interattivamente salvando la selezione
La funzione che viene proposta richiede due elenchi, contenuti in altrettanti file di testo, contenenti rispettivamente un insieme di voci e un sottoinsieme di voci da selezionare. Lo scopo è quello di cambiare il sottoinsieme selezionato e di aggiornare il contenuto del secondo file.
select_subset_save file_list_full file_list_selected\ \ selection_description unselection_description\ \ selection_word\ \ list_header list_description\ \ file_return_value_selected\ \ file_return_value_unselected
|
La funzione si avvale di un'altra che deve produrre l'opposto del sottoinsieme selezionato:
selection_invert ()
{
local LIST_FULL="$1"
local LIST_SELECTED="$2"
local LIST_UNSELECTED=""
local l=""
local s=""
local ITEM_FOUND=""
#
if [ "$LIST_SELECTED" = "" ]
then
LIST_UNSELECTED="$LIST_FULL"
else
for l in $LIST_FULL
do
ITEM_FOUND="0"
for s in $LIST_SELECTED
do
if [ "$l" = "$s" ]
then
ITEM_FOUND="1"
break
fi
done
if [ "$ITEM_FOUND" = "1" ]
then
true
else
LIST_UNSELECTED="$LIST_UNSELECTED $l"
fi
done
fi
#
echo "$LIST_UNSELECTED"
}
|
|
select_subset_save ()
{
local FILE_LIST_FULL="$1"
local FILE_LIST_SELECTED="$2"
local SELECTION_DESCRIPTION="$3"
local UNSELECTION_DESCRIPTION="$4"
local SELECTION_WORD="$5"
local LIST_HEADER="$6"
local LIST_DESCRIPTION="$7"
local FILE_RETURN_VALUE_SELECTED="$8"
local FILE_RETURN_VALUE_UNSELECTED="$9"
#
local LIST_FULL=""
local LIST_SELECTED=""
local LIST_SELECTED_VALID=""
local LIST_UNSELECTED=""
local ITEM_FOUND=""
local ITEM_SELECTION=""
local SELECTION=""
local SELECTED=""
#
local TEMPORARY=`tempfile`
touch $TEMPORARY
#
LIST_FULL=`cat $FILE_LIST_FULL | sed "s/#.*$//" 2> /dev/null`
LIST_SELECTED=`cat $FILE_LIST_SELECTED | sed "s/#.*$//" 2> /dev/null`
#
if [ "$LIST_FULL" = "" ]
then
dialog --msgbox "The file \"$FILE_LIST_FULL\" is empty!" 0 0
false
return
fi
#
# Unselected and select again.
#
LIST_UNSELECTED=`selection_invert "$LIST_FULL" "$LIST_SELECTED"`
LIST_SELECTED=`selection_invert "$LIST_FULL" "$LIST_UNSELECTED"`
#
# Item selection list.
#
for i in $LIST_SELECTED
do
ITEM_SELECTION="$ITEM_SELECTION $i ${SELECTION_WORD}_$i on"
done
for i in $LIST_UNSELECTED
do
ITEM_SELECTION="$ITEM_SELECTION $i ${SELECTION_WORD}_$i off"
done
#
# Dialog.
#
while true
do
if dialog \
--clear \
--title "$LIST_HEADER" \
--checklist "$LIST_DESCRIPTION" \
0 0 0 \
"!ALL!" "$SELECTION_DESCRIPTION" off \
"!NONE!" "$UNSELECTION_DESCRIPTION" off \
$ITEM_SELECTION \
2> $TEMPORARY
then
SELECTION=`cat $TEMPORARY`
echo "" > $TEMPORARY
#
# Do something.
#
if echo "$SELECTION" | grep "!ALL!" > "/dev/null"
then
ITEM_SELECTION=""
for i in $LIST_FULL
do
ITEM_SELECTION="$ITEM_SELECTION $i ${SELECTION_WORD}_$i on"
done
continue
#
elif echo "$SELECTION" | grep "!NONE!" > "/dev/null"
then
ITEM_SELECTION=""
for i in $LIST_FULL
do
ITEM_SELECTION="$ITEM_SELECTION $i ${SELECTION_WORD}_$i off"
done
continue
#
else
LIST_SELECTED=""
for s in $SELECTION
do
#
# Remove the double quotes.
#
SELECTED=`echo $s | sed "s/\"//g"`
LIST_SELECTED="$LIST_SELECTED $SELECTED"
#
done
#
LIST_UNSELECTED=`selection_invert "$LIST_FULL" "$LIST_SELECTED"`
#
# Save data.
#
echo -n > "$FILE_LIST_SELECTED"
for s in $LIST_SELECTED
do
echo "$s" >> "$FILE_LIST_SELECTED"
done
#
# Stop the loop.
#
break
#
fi
else
false
return
fi
done
#
rm -f $TEMPORARY
#
echo -n > "$FILE_RETURN_VALUE_SELECTED"
for s in $LIST_SELECTED
do
echo "$s" >> "$FILE_RETURN_VALUE_SELECTED"
done
#
echo -n > "$FILE_RETURN_VALUE_UNSELECTED"
for s in $LIST_UNSELECTED
do
echo "$s" >> "$FILE_RETURN_VALUE_UNSELECTED"
done
#
true
#
}
|
|
Si osservi l'esempio seguente:
select_subset_save /etc/xxx/ELENCO_COMPLETO \
/etc/xxx/ELENCO_SELEZIONATO \
"selezione di tutte le voci" \
"rimozione di tutte le selezioni" \
"attiva" \
"attivazione voci" \
"Selezionare le voci da attivare:" \
/tmp/xxx.selezionati \
/tmp/xxx.non_selezionati
|
|
In questo c'è il file /etc/xxx/ELENCO_COMPLETO, contenente un elenco di voci (ogni voce deve costituire una parola sola), quindi c'è il file /etc/xxx/ELENCO_SELEZIONATO con un sottoinsieme delle voci del primo file. Attraverso la selezione che si esegue con la funzione, il file /etc/xxx/ELENCO_SELEZIONATO viene aggiornato con il nuovo sottoinsieme, ma in ogni caso si genera il file /tmp/xxx.selezionati con le voci selezionate e il file /tmp/xxx.non_selezionati con le altre voci.
Appunti di informatica libera 2008.11.27.00.26 anteprima --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com> <http://informaticalibera.net> Edizione di prova: si prega di segnalare i difetti.
Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome raccolta_di_funzioni_per_una_shell_posix.htm
[successivo]
[precedente]
[inizio]
[fine]
[indice generale]
[indice ridotto]
[indice analitico]

