Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


пятница, 26 октября 2018 г.

bash: список имеющихся расширений файлов в каталоге и подкаталогах

Есть у меня сервер на самбе, вполне себе рабочий. В нем есть поддержка "корзины" (в отличие от микрософтовских серверов). Но вот какая штука: в корзину валятся всякие файлы, в т.ч. и временные. И за рабочий день их может набраться очень много.
Каждую ночь из "корзин" удаляются файлы старше 30 дней и просто очень толстые, а также - временные. Но иногда временных очень уж много. Стало быть, надо не помещать их в корзину вовсе.
Решение очевидно:

(/etc/samba/smb.conf или его инклюд)
[global]
    vfs objects = recycle
    recycle:keeptree=yes
    recycle:repository= .recycle/%U
    recycle:exclude=*.tmp,~*,*.~*

Однако, кроме трёх указанных типов (расширений имён) файлов могут удаляться и самые разные другие, в т.ч. и такие, которым незачем занимать место в "корзине". Просматривать всё вручную - не труЪ. Логично будет сначала составить список имеющихся расширений, а уже от него плясать. Но наконец-то я нашел ситуацию, для которой в никсах, кажется, нет подходящей утилиты - для выделения только расширения файла. Выделить имя - есть basename, выделить путь - dirname, а вот для выделения суффикса ничего нет.

Покопался, нашел замечательно:

(чего-то там) |awk -F . '{print $NF}'

Пример самоочевиден: объявляем точку разделителем полей и выводим то, что есть в имени файла правее последней точки. Не очень надежно, если есть файлы без расширения, и не очень быстро из-за лишних обращений к awk, но для моих целей подошло:

# cd /var/samba/share
# find -depth -type f -wholename *recycle/* |awk -F . '{print $NF}'|sort|uniq

На выходе получаем отсортированный список уникальных расширений файлов, попавших в "корзины". Дальше осталось только выбрать самые ненужные и добавить их в список настроек виртуальной файловой системы "корзина".

Кроме того, на любимом StackExchange нашел еще приятное обсуждение по этому поводу.

Ну а для любителей башизмов, использующих встроенные возможности по максимуму, есть вот такая прелесть:

# Из начала строки убираем самое длинное вхождение "*/", получаем имя файла с расширением 
filename="${fullpath##*/}";
# Берем подстроку от начала строки (поз. 0) до позиции, где начинается собственно имя файла
### TM: по сути, именно это делает команда dirname
directory="${fullpath:0:${#fullpath} - ${#filename}}";
# Отрезаем самую короткую подстроку, состоящую из точки и как минимум одного "обычного" символа, с конца имени файла
### TM: по сути, именно это делает команда basename
base="${filename%.[^.]*}";
# Берем подстроку от позиции "длина базового имени" до конца полного имени файла
extension="${filename:${#base} + 1}";
# Если на выходе у нас есть что-то в $extension, но ничего нет в $base, то файл был без расширения
if [[ -z "$base" && -n "$extension" ]]; then
  base=".$extension";
  extension="";
fi
echo -e "Оригинал:\t'$fullpath':\n\tПуть:\t'$directory'\n\tПолное имя файла:\t'$filename'\n\tБазовое имя:\t'$base'\n\tРасширение:\t'$extension'"
Специально оставил даже форматирование, как оно было в оригинале, только комментарии перетолмачил.

среда, 3 октября 2018 г.

bash: Получение читаемой информации о пользователе из ADDS

Понадобилось мне проверить, что случилось с пользователем. Под рукой только домашняя убунта, лезть терминалом на сервер на работе не комильфо.

Но есть настроенный ldapsearch, которым мы и воспользуемся. Изначально фрагмент писался для получения данных о компах, поэтому переменная, которую ищем, называется $comp

NB! В итоговом массиве есть только одна переменная с индексом memberof, хотя пользователь может входить в несколько групп. Список групп я получаю более другими способами, поэтому ситуация в этом скрипте не анализируется. Возможно надо проверять значение индексера, и если он есть memberof, то дописывать значение параметра к переменной с таким индексом. Лично мне это просто не требуется.

#!/bin/bash
# похоже, что без промежуточного файла не обойтись - вывод ldapsearch напрямую не перехватывается
comp=$1
unset ldapData
# ldapData - ассоциативный, а не нумерованный массив!
declare -A ldapData
ldapsearch -o ldif-wrap=no -D ПОЛЬЗОВАТЕЛЬ -x -w "ПАРОЛЬ" "(cn=$comp)">/tmp/ldifDataFile
# список полей с датами, которые надо декодировать
# ведущий и хвостовой пробелы обязательны
datesList=" lastlogon pwdlastset badpasswordtime accountexpires "
while read ldiffPar ldiffData;do
  if [ "${ldiffPar:0:1}" == "#" ] || [ ${#ldiffPar} -eq 0 ]; then continue; else

# приводим ldiffPar к нижнему регистру
    ldiffPar=${ldiffPar,,}

# а для переменной-индекса убираем все двоеточия, сколько бы их там ни было
    indexer=${ldiffPar//:/}

# если два последних символа имени атрибута два двоеточия, значит он кодированный и нуждается в декодировании
    if [ ${ldiffPar: -2} == "::" ]; then
      ldapData[$indexer]="$( echo $ldiffData|base64 -d )"
    else
      ldapData[$indexer]="$ldiffData"
    fi
# если название атрибута в ADDS есть в списке $datesList, то переводим дату из
# формата MS в человекочитаемый
# не очень надежный способ поиска, поэтому ищем "пробел-индексер-пробел", а не просто "индексер"
    if  [[ "$datesList" = *" $indexer "*  ]]
    then
      ldapData[$indexer]=$( date -d @$(( ${ldapData[$indexer]}/10000000-11644473600 )) +%Y-%m-%d\ %H:%M:%S)
    fi
# отдельное внимание состоянию пользователя
    if [ $indexer == "useraccountcontrol" ]
    then
      isActive=$(( ${ldapData[$indexer]} & 2 ))
      if [ $isActive -eq 0 ]; then uacState="АКТИВЕН "; else uacState="не активен ";fi
      ldapData[$indexer]=$uacState${ldapData[$indexer]}
    fi
    echo ldapData[$indexer]=${ldapData[$indexer]}
  fi
done


На выходе получаем список всех непустых атрибутов пользователя.