VNC

VNC (Virtual Network Computing) - система дистанционного управления рабочим столом удалённого компьютера.

В отличии от системы 'X window', предназначенной для запуска отдельных приложений, VNC позволяет получить доступ ко всему рабочему столу целиком. Кроме того, преимуществом VNC перед X window является возможность отключиться от рабочего стола, оставив его работать в фоне вместе со всеми приложениями, а после подключиться с этого же или другого компьютера.

С другой стороны, при использовании X window тратится существенно меньше ресурсов сервера, чем при VNC: в первом случае на сервере не запускается ничего дополнительного, кроме самого приложения, причём даже 'экран' для вывода изображения является полностью виртуальным (данные просто передаются на компьютер пользователя и визуализируются на нём), а в случае VNC на сервере запускается оконный менеджер (GNOME, KDE, XFCE, …), потребляющий как оперативную память, так и ресурсы процессора, изображение формируется на самом сервере и на компьютер пользователя передается не абсолютно точно, а в оптимизированном виде (условно говоря, как JPG-изображение).

В отличии от X window, часть VNC, запускаемая на удалённом компьютере, называется 'сервером', а 'клиент' работает на компьютере пользователя.

Работа с удалённым рабочим столом будет состоять в следующем:

  • На кластере с помощью PBS запускается задача, запрашивающая определённые ресурсы (не более одного узла) и запускающая на выделенном узле VNC-сервер.
  • На персональном компьютере (считаем, что он работает под управлением Windows):
    • создаётся SSH-туннель до этого узла через подключение к интерфейсному серверу кластера;
    • запускается VNC-клиент, подключающийся через туннель к VNC-серверу, работающему на узле.
  • Далее через этого клиента производится работа с удалённым рабочим столом узла - запускаются нужные программы и т.д.
  • При необходимости можно разорвать соединение, оставив работать задачи на узле, а потом подключиться с этого же или с другого персонального компьютера.
  • По истечении запрошенного задачей времени VNC-сервер и все работающие в нём приложения будут принудительно завершены.

Перед первым использованием VNC Вам необходимо:

  1. Выполнить на вычислительном комплексе команду 'vncpasswd' и установить пароль, который будет использоваться для доступа к Вашему рабочему столу. Помните, что рабочий стол запускается с правами Вашего пользователя и любой подключившийся будет иметь полный доступ к Вашим файлам. Не используйте слишком простой пароль.
  2. Создать или модифицировать файл '~/.vnc/xstartup' в своей домашней директории на комплексе до такого вида:
    #!/bin/sh
    xrdb $HOME/.Xresources
    xsetroot -solid grey
    gnome &
  3. Указать, что это исполняемый файл:
    chmod +x ~/.vnc/xstartup
  4. Установить на своём персональном компьютере VNC-клиент. Имеется большое количество бесплатных реализаций, совместимых друг с другом, но предлагается использовать TightVNC, т.к. на серверах кластера используется именно это приложение. При установке укажите, что Вам нужна только клиентская часть, а не серверная - иначе Вы обеспечите возможность подключения к рабочему столу своего персонального компьютера.
  5. Ознакомиться с принципами туннелирования TCP-трафика через соединение SSH и выяснить, какие TCP-порты на Вашем локальном компьютере не используются (cписок используемых в данный момент портов на операционной системе Windows-семейства можно узнать командой 'netstat -an -p tcp' - смотреть на число после двоеточия во втором столбце.). Если Вы хотите иметь возможность работать через VNC одновременно с несколькими удалёнными рабочими столами, то Вам надо подготовить такое-же количество неиспользуемых локальных портов. Например, если на Вашем локальном компьютере не запущен VNC-сервер, то скорее всего можно будет использовать TCP-порты 5900 и выше. Напоминаем, что номера портов на локальном и на удалённом компьютерах при туннелировании не обязаны совпадать.
  6. Подготовить скрипты, которые будут запускаться на локальной Windows и создавать туннели. Нужно такое же количество скриптов, сколько одновременных VNC-сессий будет использоваться). Шаблон для скрипта 'tunnel2vnc.cmd':
    @echo off
    
    SET [SERVER]="cn178:5903"
    SET [LOCALPORT]=5900
    SET [LOGIN]="логин@имя_интерфейсного_сервера"
    SET [KEY]="C:\Documents and Settings\user\nusc.ppk"
    
    plink -v -i %[KEY]% -N %[LOGIN]% -L %[LOCALPORT]%:%[SERVER]%

    В скрипте необходимо указать переменные 'LOGIN', 'KEY' (путь до закрытой части персонального ключа) и 'LOCALPORT'. 'SERVER' надо будет корректировать каждый раз после запуска VNC-сервера, но об этом будет сказано ниже.

  7. Создайте приведённый ниже скрипт 'run-vnc.sh', с помощью которого через PBS будет запускаться VNC-сервер. Скорректируйте его, изменив запрос ресурсов, а также переменную 'GEOMETRY' (в которой указывается разрешение создаваемого VNC экрана):
    #!/bin/sh
     
    #PBS -l walltime=00:60:30
    #PBS -l select=1:ncpus=8:mem=16000mb
     
    VNCSERVER='/usr/bin/vncserver'
    GEOMETRY='1024x768'
     
    cd $PBS_O_WORKDIR
     
    ##----- Get walltime from this script: -----
    w=$(cat ${BASH_SOURCE[0]}|grep -e '^#PBS -l walltime='|awk -F= '{print $2}')
    w=$(echo $w|awk -F: '{print 3600*$1+60*$2+$3}')
    let "walltime=$w-30"
     
    ##----- Find first unused VNC port & display: -----
    display=0
    for i in `seq 1 20` ; do
        let "port = 5900 + $i"
        if [ $(netstat -ant|awk '{print $4}'|grep -c $port) -eq 0 ] ; then
            display=$i
            break
        fi
    done
    if [ "$display" == '0' ] ; then
        echo 'ERROR: no free VNC-port was founded.'
        exit 100
    fi
     
    ##----- Save name of the node and port: -----
    log="$(echo $PBS_JOBID|awk -F. '{print $1}')".log
    node="$(uname -n)"
    echo "$node:$port" >> $log
     
    ##----- Start VNC Server, check it and wait: -----
    $VNCSERVER -geometry $GEOMETRY -depth 24 :${display} 2>&1
    sleep 10
    if [ $(netstat -ant|awk '{print $4}'|grep -c $port) -eq 0 ] ; then
        echo 'ERROR: VNC do not start!'
        exit 100
    fi
    sleep $walltime
     
    ##----- Stop VNC Server: -----
    $VNCSERVER -kill :${display} 2>&1
    rm -f $log >/dev/null 2>&1
    rm -f ~/.vnc/$node:$display.log >/dev/null 2>&1
    rm -f ~/.vnc/$node:$display.pid >/dev/null 2>&1


Обращаем внимание на следующие моменты, связанные с работой скрипта 'run_vnc.sh':

  1. Скрипт не только запускает VNC-сервер, но и корректно останавливает его перед завершением работы. Чтобы не указывать 'walltime' дважды и по ошибке не задать разные значения в запросе ресурсов и в задержке перед выключением, сделано так, что скрипт считывает свой собственный код и определяет запрошенный 'walltime'. Такой способ пришлось использовать, т.к. PBS не предоставляет возможности узнать 'walltime' через переменные окружения (аналогично '$PBS_O_WORKDIR'). Кроме того, с поправкой на возможные накладные расходы на запуск и завершение VNC, задержка между ними (переменная '$walltime') уменьшается на 30 секунд по сравнению с запрошенным временем ('#PBS -l walltime=….').
  2. Параметр 'GEOMETRY' содержит разрешение виртуального экрана (в точках в формате 'ширина'x'высота'), который будет создан на удалённом компьютере. Рекомендуется подобрать его в соответствии с разрешением своего монитора таким образом, чтобы не возникали полосы горизонтальной и вертикальной прокрутки - т.е. на несколько десятков точек меньше, чем разрешение монитора. Изменить разрешение экрана уже работающего VNC-сервере нельзя, только остановить этот сервер и запустить новый.
  3. На одном удалённом компьютере может работать одновременно несколько VNC-серверов, запущенных разными пользователями. Принято, что они ждут подключения на TCP-портах, начиная от 5900. Поэтому скрипт автоматически определяет первый свободный порт и связанный с ним 'экран' (переменные 'port' и 'display' в скрипте).
  4. После запуска задачи скрипт сохраняет имя узла, на котором был запущен, и номер TCP-порта VNC-сервера в файл в текущей директории с именем 'XXX.log', где XXX - номер соответствующей задачи. Примерно в таком виде:
    cn178:5903
  5. FIXME Иногда VNC сервер не может успешно запуститься. Поэтому непосредственно после запуска добавлена проверка, начал ли использоваться выделенный ему порт.

После постановки задачи в очередь командой 'qsub run-vnc.sh' и последующего её запуска необходимо:

  1. Узнать из файла 'XXX.log' выделенный задаче узел и TCP-порт.
  2. Вписать их в с параметр 'SERVER' скрипта 'tunnel2vnc.cmd'. Запомнить значение переменной 'LOCALPORT'.
  3. Запустить этот скрипт на своём персональном компьютере, убедиться, что последние строки в появившемся окне содержат 'Access granted' и 'Local port AAAA forwarding to cnBBB:CCCC'. Свернуть окно (не закрывать :!:).
  4. Запустить приложение 'TightVNC Viewer'. В поле 'Remote Host' ввести '127.0.0.1::LOCALPORT' (т.е., например '127.0.0.1::5900' без кавычек). Нажать кнопку 'Connect'.
  5. Должно появиться окно для ввода пароля, указанного ранее командой 'vncpasswd'. Вписать пароль, нажать 'Ok'. Если же вместо окна для ввода пароля будет получено сообщение 'Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение', значит, что-то было сделано неправильно.
  6. Должно появиться окно с рабочим столом удалённого компьютера.
  7. Закрытие этого окна 'крестиком' будет оставлять сессию работать в фоне и к ней можно будет подключиться позднее. Причём и с другого компьютера: только на нём надо будет также выполнить все указанные выше шаги.
  8. В случае длительной неактивности операционная система удалённого компьютера заблокирует экран и для продолжения работы потребуется ввести пользовательский пароль (не тот, который указывался командой 'vncpasswd'). Проблема в том, что этот пароль отсутствует в принципе, т.к. для авторизации внутри кластера используются ключи (не те, что используют пользователи при авторизации на интерфейсном сервере). Поэтому после первого подключения надо выполнить следующую процедуру: нажать кнопку 'Компьютер', затем 'Control Center', в разделе 'Look and Feel' выбрать 'Screensaver' и убрать галочку 'Lock screen when screensaver is active'. Также можно отключить и 'Activate screensaver when computer is idle'. Данную процедуру надо выполнить только один раз: во всех VNC-сессиях, запущенных позже, настройки будут уже установлены.


Помните, что:

  • По истечении 'walltime' VNC-сервер на удалённом компьютере будет принудительно закрыт, вместе что всеми работающими в нём приложениями. Поэтому настоятельно рекомендуется самостоятельно контролировать, сколько времени осталось до завершения каждой задачи и корректно закрывать все работающие в этой сессии приложения.
  • Некоторые приложения (например, Firefox), при запуске блокируют (монопольно занимают) свои файлы в Вашей домашней директории. Поэтому одновременный запуск второго экземпляра (например, работающего на другом сервере) может быть невозможен.