Задумала как-то одна компания перейти на ПО свободное. И скачали себе линукс на все компьютеры, и сервер с дисками заморскими поставили, и учетные записи для пользователей сделали. И приказал начальник чтобы все сотрудники поставили себе пароли заковыристые. А они хоть и послушали рассказы о том, что за зверь перед ними, а вот где поменять пароль не знают. Или в настройках найти не могут. А от консоли бегут сломя голову. И начинают бегать к админу со словами «админ-админушка, помоги найти кнопочку», и начинает админушка бегать да нервничать, от дум важных отвлекается...

Не секрет, что для многих пользователей (особенно не связанных напрямую с IT) переход на новую операционную систему и ПО часто проходит болезненно. И во многом это связано с привычками. Люди запоминают что где находится на их компьютере и, если все переставить — они теряются. В результате многие простые действия могут вызывать сложности, такие как потеря времени и нервов.

Появилась идея: а что, если для задачи, требующей незамедлительного вмешательства пользователя (вроде замены пароля из былины выше), еще не знакомого с интерфейсом системы, ему явно дать окно с возможностью эту задачу решить? В поисках простого решения я наткнулся на zenity. Это небольшая утилита, позволяющая выводить на экран диалоговые окна. Она использует GTK+ и, как оказалось, в большинстве популярных дистрибутивов линукса идет в комплекте. В дополнение к этому ее можно использовать прямо в скриптах на BASH, что дает возможность быстро «на коленке» сделать скрипт и запустить его у пользователя в определенное время. Рассмотрим пример:

function change_password() {
    local passwords=$(zenity --forms --title="Change your password"         --text="Set new password (minimum length 8 characters)"         --separator=","         --add-password="Your password"         --add-password="Repeate password")

    local password1=$( echo $passwords | awk -F ',' '{print $1}' )
    local password2=$( echo $passwords | awk -F ',' '{print $2}' )

    if [[ $password1 == $password2 ]]; then
        if [[ ${#password1} == 0 ]]; then
            zenity --warning --text "Please, select Your password"
            change_password
            return
        fi

        if [[ ${#password1} < 8 ]]; then
            zenity --warning --text "Your password too easy."
            change_password
            return
        fi

        local username=$(whoami)

        # закомментируем само изменение пароля
        # чтобы незадачливый пользователь Ctrl+C - Ctrl+V случайно его себе не поменял
        #echo "$username:$password1" | chpasswd
		
        local expire_time=$(chage -l $username | awk 'FNR==2{print $4}')
        local full_name=$(cat /etc/passwd | grep "^$username"             | awk -F ':' '{print $5}' | awk -F ',' '{print $1}')

        zenity --info --text "$full_name, Your password has been changed. Your new password expires: $expire_time"
    else
        zenity --warning --text "Passwords does not match"
        change_password
        return
    fi
}

change_password

В результате мы получаем окошко с формой для пароля, которое «само покажется» вероятно с использованием утилиты at или ее аналога пользователю и ему останется только ввести свой новый пароль, сэкономив время и ему и администратору. Выглядит это примерно так (используется стандартное оформление окон из вашей системы):

image

Zenity не только показывает окно, но и выводит в стандартные вывод то, что пользователь в окне сделал. В нашем случае он заполнил два поля в форме. Нам нужно этот самый вывод перехватить. Таким образом мы можем получить значения всех полей из диалогового окна в одной строке через разделитель — по умолчанию символ "|", в примере мы заменяем его на запятую. Назначение параметров zenity говорят сами за себя, особенно если сразу смотреть на результат.

passwords=$(zenity --forms --title="Change your password"     --text="Set new password (minimum length 8 characters)"     --separator=","     --add-password="Your password"     --add-password="Repeate password")

Дальше нам остается только обработать полученные данные (проверка на длину меньше 8 символов для пароля — это для примера, никогда так не делайте!), и сообщить пользователю о результатах. Для этого как нельзя кстати оказались окна с сообщениями, которые создаются еще проще, чем с формами:

zenity --warning --text "Your password too easy." --width=300

image

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

username=$(whoami)
expire_time=$(chage -l $username | awk 'FNR==2{print $4}')
full_name=$(cat /etc/passwd | grep "^$username"     | awk -F ':' '{print $5}' | awk -F ',' '{print $1}')

zenity --info --width=400 --text "$full_name, Your password has been changed. Your new password expires: $expire_time"

image

Как вариант можно использовать и стандартные уведомления:

zenity --notification --window-icon="info"     --text="$full_name, Your password has been changed. Your new password expires: $expire_time"

image

WARNING! В старых версиях пакета zenity есть баг, из-за которого процесс, создающий окно с уведомлением не может завершиться. Это решается добавлением ненулевого таймаута:

zenity --notification --window-icon="info" --text="..." --timeout=1

Идея с использованием таких окошек была положительно воспринята и вскоре появилась мысль попросить пользователя оценить работу своего копмьютера по пятибальной шкале. Это вообще очень полезное занятие — позволяет отследить скорость увеличения довольных людей и выделить тех, у кого больше всего трудностей с освоением нового окружения, и, соответственно, принять меры по устранению трудностей. В простейшем виде это выглядело так:

mark=$(zenity --scale     --text "Rate your experience"     --value=3     --min-value=1    --max-value=5     --step=1)

if [[ $? == 0 ]]; then
    zenity --notification --window-icon="info" --text="Thank You!" --timeout=1
fi

Названия опций интуитивно понятны и не требуют пояснений.

image

К сожалению, zenity не умеет заменять такую шкалу на звездочки (есть мнение, что звездочки интуитивно понятнее), но, вскоре нашелся аналог со списком:

zenity --list --text="What do you think about your PC?"     --radiolist --column "Pick" --column "Opinion"     TRUE "All is good"     FALSE "All is good, but..."     FALSE "I don't know"     FALSE "Too dificult to use it"     FALSE "A-A-A \(O_O)/ A-A-A"     --height=350

image

С использованием cron`a можно раз в день запускать и смотреть результаты. Осталось только решить вопрос с передачей собранных данных на сервер. Кажется, хорошей идеей будет приобщить систему мониторинга, которая и так уже имеет агента на каждом компьютере в рамках эксперимента — и рисовать графики для опросов пользователей.

Несмотря на то, что примеры в этой статье явно не самые актуальные, я надеюсь, что они наведут кого-нибудь на интересные мысли по поводу использования графических интерфейсов в небольших скриптах для связи с пользователями. Возможно это будут важные сообщения для всех работников (в духе команды wall, только с окошком), оповещения о начале обеденного перерыва или голосования о месте проведения корпоратива. Хочу также отметить, что если вы знаете готовые программные решения для такого рода задач — вы можете поделиться ими в комментариях, а мои скрипты «на коленке» — это не более чем интересный эксперимент, который может в последствии перерасти в нечто большее.

В заключение еще раз привожу ссылку на мануал по zenity: https://help.gnome.org/users/zenity/stable/

Комментарии (15)


  1. AcidVenom
    06.04.2016 12:01

    Your password too easy.
    is забыли.


    1. lolipop
      06.04.2016 12:03
      +2

      и не только тут.


  1. lolipop
    06.04.2016 12:03
    -2

    image
    image
    вам бы школьную программу повторить.


    1. GoldJee
      06.04.2016 14:28
      +2

      Как грубо. Может, лучше все же сообщать авторам о грамматических ошибках в ЛС?

      По мне, статья замечательная. Кроме того, описанные в ней практики ведут к повышению качества сервиса ИТ-службы. Рад, что мы постепенно двигаемся от мышления «юзвери тупые» в сторону «наша задача помочь юзерам и облегчить их работу».


    1. TokminD
      07.04.2016 10:02

      Небольшая грамматическая ошибка нисколько не меняет впечатления о статье. Коротко, понятно и познавательно. В практике пока такое не нужно, но подход к решению понравился.


  1. past
    06.04.2016 12:38
    +5

    • Есть более универсальное решение — dialog.
    • Если у Вас корпоративное решение с линуксом и шарами, то логично будет внедрить Single Sign-on, чтобы иметь централизованное управление.


    1. rgaliull
      06.04.2016 13:23
      +1

      интересно. Можно подробнее?
      На чем делать SSO?


  1. RPG
    06.04.2016 13:17

    Попробуйте ещё yad — это форк Zenity, но более продвинутый и устраняет многие недостатки Zenity. Но главное — можно делать практически произвольные формы.

    Для проверки качества пароля используйте cracklib-check, она умеет сообщать вид «слабости» пароля, используется в стандартном PAM:

    $ cracklib-check <<< 123
    123: it is WAY too short
    

    Для отправки уведомлений можно использовать notify-send, там багов таких нет.


    1. kvaps
      06.04.2016 16:27

      Хочу отметить, что zenity существует так же и под windows.
      А в комбайне с mingw он позволит исполнять ваши скрипты и под windows.


  1. yermulnik
    06.04.2016 19:08

    function change_password() {
        local passwords=$(zenity --forms --title="Change your password"         --text="Set new password (minimum length 8 characters)"         --separator=","         --add-password="Your password"         --add-password="Repeate password")
    
        local password1=$( echo $passwords | awk -F ',' '{print $1}' )
        local password2=$( echo $passwords | awk -F ',' '{print $2}' )
    

    Лёгким мановением awk'ом рубите тех, кто хочет использовать запятые в пароле?


    1. sfi0zy
      06.04.2016 19:49

      Должен с вами согласиться, в качестве разделителей лучше использовать символы, которые пользователь не сможет ввести с клавиатуры


      1. yermulnik
        06.04.2016 22:09

        Либо последовательность символов, которую пользователь введёт с очень низкой вероятностью.


        1. yosemity
          07.04.2016 01:02

          Предлагаю использовать матерное слово, или фамилию гендира, тогда юзер вообще обалдеет от такого «ИИ». Или паранойя даст росток :)


          1. 3vi1_0n3
            11.04.2016 19:07

            И вообще лучше тогда awk не использовать:

            passlen=$((${#passwords} / 2))
            password1=${passwords:0:$passlen}
            password2=${passwords:$passlen+1}
            

            Заодно и разделитель не важно какой будет


            1. 3vi1_0n3
              11.04.2016 19:10

              P.S. function считается deprecated, рекомендуется использовать просто

              change_password()