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

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


четверг, 28 марта 2019 г.

Немного о regexp в MySQL

Таблетка для памяти:

Есть служба, компы в которой могут иметь имена от cnt30150 до cnt30149z.
Шаблон для тех, кто понимает:

cnt30[0-9]{3}[0-9a-z]{1}

При этом только 3 цифры после cnt30 есть собственно номер компа, а последний знак - дополнительный индекс, который может повторяться у разных компов.

Для отбора компов вышеупомянутой службы из базы OCS Inventory используем такое регулярное выражение:

select id,name from hardware where name rlike "cnt301(3[5-9]{1}|4[0-9]{1})."

То есть, выбираем компы, имена которых начинаются с cnt301, после чего идет либо тройка, за которой должна следовать цифра от 5 до 9, либо четверка, после которой должна быть цифра от 0 до 9, и заканчивается это одним любым символом.

Дополнительно стоит заметить, что для rlike (он же - regexp) шаблон указывается в двойных кавычках, как это делается для имени поля, а не в апострофах, как обычная строка.

Конечно, можно было задать этот же диапазон как:

select id,name from hardware where name >= 'cnt301350' and name <= 'cnt30149z'

что тоже правильно, но ведь это не так красиво, а?

пятница, 15 марта 2019 г.

bash: разница между двумя моментами времени

Есть у нас хитрая система учета рабочего времени, которая требует указывать продолжительность выполненных работ исключительно в минутах. Например, с 8:45 до 13:30 я был на выезде. Вопрос: сколько минут я должен записать?

Не, оно, конечно, несложно - "без 15 минут 5 часов", то есть, 4 часа 45 минут или 285 минут.
Но в гробу я видал заниматься временнОй арифметикой в уме - у меня есть и более интересные занятия. Поэтому написал небольшой не оптимизированный скрипт без наворотов, который чисто средствами баша считает разницу в минутах (и не только) между двумя моментами времени в пределах одних суток. Допиливать его под переход суток и т.п. мне лень, допилю, когда и если понадобится.

(примечание: между двумя вхождениями "Descriptions" идет длинный коммент в стандарте heredocs - см. руководство по башу, чтобы не ставить кучу диезов)

#!/bin/bash
<<Descriptions

 timediff - разница между двумя временами в пределах суток
 $1 - начальное время
 $2 - конечное время

 Формат параметров:
 ч:м[:с]
 ведущие нули не обязательны, но если нужно указать только минуты, то ноль часов указывать обязательно:
 :12:34 - неправильно
 0:12:34 - правильно

 Проверки на допустимость параметров не делаются, поэтому в случае чего вываливается с ошибкой "смените пользователя"

Descriptions

# с учетом возможной переделки, используем переменные для времен
# пока что $TimeX и $n - одно и то же, но в будущем это может измениться
TimeS=$1
TimeF=$2

# TimeStamp Start/Finish
TSS=$( date +%s -d $TimeS )
TSF=$( date +%s -d $TimeF )

# Разница в секундах, целых минутах, целых часах
DiffS=$(( $TSF-$TSS ))
DiffM=$(( $DiffS/60 ))
DiffH=$(( $DiffM/60 ))
# Сколько секунд сверх целых минут и минут сверх целых часов
ExtraS=$(( $DiffS-$DiffM*60 ))
ExtraM=$(( $DiffM-$DiffH*60 ))

# продолжительность в разных единицах
echo ${DiffS}s
echo ${DiffM}m
echo ${DiffH}h

# в минутах и секундах (минут может быть больше 60)
echo ${DiffM}:${ExtraS}"(m:s)"
# в часах, минутах и секундах
echo ${DiffH}:${ExtraM}:${ExtraS}"(h:m:s)"

Например:

$ timediff.sh 8:45 13:30
17100s
285m
4h
285:0(m:s)
4:45:0(h:m:s)


пятница, 22 февраля 2019 г.

МФУ Canon ir1022 / mf3110 и Windows 10/64

Интересное, знаете ли, кино. Есть у нас в конторе некоторое количество МФУ этой фирмы: ir1022 разных модификаций и один штука mf3110. Худо-бедно они дружили с XP и Win7, 32-битными. Но пришла пора обновлять рабочие станции. Обновили, стоит не топовое, но очень приличное железо, на котором очень резво крутится Win10/64 сборки 1809, разумеется, лицензионная, всё по-честному.

И вот тут начались проблемы. Драйвер UFR II для этой ОС для моделей 1022 (с факсом и без) нашелся без особых проблем, и эти каноны заработали - и как сетевые и как локальные принтеры. Как сетевые сканеры мы их не использовали: не умеют они сканировать с сохранением на SMB-шары, как это прекрасно делают многочисленные Kyocera. Да и бог с ними, там, где эти каноны стоят, они всегда использовались только как локальные сканеры по USB.

суббота, 9 февраля 2019 г.

md5 под Windows

Довольно долго использовал найденную незнамо где утилиту md5sum.exe, явно портированную из никсов. Но неожиданно обнаружилось, что при работе с большими файлами под WinServer 2016 она начинает жрать память, как свинья помои.
Не уверен, что проблема именно в утилите, которая прекрасно работала под серверами 2008 и 2012, но решать ее надо.

Посмотрим, как себя поведет штатная утилита от Microsoft fciv. Сразу скажу, что с русскими именами файлов это ископаемое (2004) работать не умеет:


Видно, что слово "образ" (5 букв) превратилось в 4-буквенную абракадабру, и такой файл утилита найти не может. Тот же самый файл с названием из латинских букв обрабатывается на ура.


Результат совпадает с результатами от /usr/bin/md5sum. Замеры расхода памяти в процессе показывают, что лишнюю память fciv не потребляет.

На странице по ссылке указано, что fciv работает под 2000, ХР и 2003. Но у меня оно без проблем заработало под Win10 сборка 1809. Ну и, как обычно, при перенаправлении результатов в файл в конце строки появляется "вк/пс" вместо стандартного никсового "пс", так что созданные с помощью fciv файлы md5sums надо преобразовывать, убирая лишний символ, чтобы /usr/bin/md5sum могла сверять по ним проверяемые файлы.

пятница, 8 февраля 2019 г.

Клиент Windows под VirtualBox не может обратиться к \\vboxsvr

Дано: есть Windows 10, установленная в VirtualBox под Ubuntu.
Требуется: обратиться к "общей папке"
Ситуация: не получается, "не найдено сетевое имя \\vboxsvr", хотя раньше всё работало.

Ответ: обновление винды имеет дурную привычку ломать установленные системные программы. Например, напрочь сносится штатный виндовый RSAT. Судя по всему, то же самое происходит и с компонентами Virtualbox Guest Additions.

Решение: переустановить VBGA. Даже если ранее была установлена та же самая их версия. После этого "общие папки" снова прекрасно находятся.

пятница, 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


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