Распространение ПО в Linux: контейнеры или пакеты? Денис Силаков $ flatpak install --from https://s3.amazonaws.com/alexlarsson/skype-repo/skype.flatpakref $ flatpak run com.skype.Client ----------------------------------------------------------------------------------------- Оптимизация с помощью виртуализации. Организуем несколько рабочих мест из одного десктопа. Часть 3 Андрей Семенов 01:00,x-vga=on 01:00.0,x-vga=on ps –axww | grep kvm -device 'vfio-pci,host=01:00.1,id=hostpci0.0,bus=pci.0, addr=0x10.0,x-vga=on,multifunction=on' \ -device 'vfio-pci,host=01:00.0,id=hostpci0.1,bus=pci.0, addr=0x10.1' \ -device 'vfio-pci,host=01:00.0,id=hostpci0.0,bus=pci.0, addr=0x10.0,x-vga=on,multifunction=on' \ -device 'vfio-pci,host=01:00.1,id=hostpci0.1,bus=pci.0, addr=0x10.1' \ 01:00.0;01:00.1,x-vga=on /usr/sbin/xl –vvv create /path/to/virtcfgfiles/virt.hvm file:/path/disk1.raw,hda,w file:/path/disk1.raw,hdb,w ----------------------------------------------------------------------------------------- Мультипортовый OpenVPN-сервер с аппаратным VPN-шлюзом Петр Рыбаков $ sudo apt-get update $ sudo apt-get install openvpn easy-rsa isc-dhcp-server ufw $ make-cadir ~/openvpn-ca export KEY_COUNTRY="USA" export KEY_PROVINCE="CA" export KEY_CITY="SanFrancisco" export KEY_ORG="Fort-Funston" export KEY_EMAIL="me@myhost.mydomain" export KEY_OU="MyOrganizationalUnit" export KEY_NAME="server" $ cd ~/openvpn-ca $ source vars $ ./clean-all $ ./build-ca $ ./build-key-server server $ ./build-key client1 $ ./build-dh $ openvpn --genkey --secret keys/ta.key //Порт, который будет слушать сервер port 443 //Используемый сервером транспортный протокол proto tcp //Имя сетевого адаптера, используемого данным сервером dev tap0 //Режим работы сервера на втором уровне server-bridge //Включение принудительного перенаправления трафика клиентов в VPN push "redirect-gateway def1 bypass-dhcp" //Возможность клиентам сервера видеть друг друга. Остальные опции не являются ключевыми для рассматриваемой конфигурации и могут быть использованы по усмотрению client-to-client # This configuration designed for use with blocks for 3 servers on one machine remote my.own.vpn 53 udp remote my.own.vpn 53 tcp remote my.own.vpn 443 tcp sftp serviceaccount@my.own.vpn:configs/client1.ovpn auto br0 iface br0 inet static bridge_ports tap0 tap1 tap2 network 192.168.11.0 address 192.168.11.1 netmask 255.255.255.0 broadcast 192.168.11.255 auto tap0 iface tap0 inet manual auto tap1 iface tap1 inet manual auto tap2 iface tap2 inet manual INTERFACES="br0" option classless-static-routes code 121 = array of unsigned integer 8; option ms-classless-static-routes code 249 = array of integer 8; option classless-static-routes 0, 192,168,11,1; option ms-classless-static-routes 0, 192,168,11,1; # START OPENVPN RULES # NAT table rules *nat :POSTROUTING ACCEPT [0:0] #Allow traffic from OpenVPN client to eth0 -A POSTROUTING -o ens4 -j MASQUERADE -A POSTROUTING -o ens4 -j LOG --log-prefix "POSTROUTING" COMMIT # END OPENVPN RULES # opkg update # opkg install openvpn-openssl option proto 'dhcp' config interface 'tap0' option ifname 'tap0' option proto 'dhcp' ################################################### # Sample to include a custom config file. # ################################################### config openvpn custom_config # Set to 1 to enable this instance: option enabled 1 # Include OpenVPN configuration option config /etc/openvpn/%configname%.ovpn # /etc/init.d/openvpn enable ----------------------------------------------------------------------------------------- Использование шаблонов веб-сервера Сергей Яремчук server { listen 80; server_name *.example.org; set $subdomain ""; if ($host ~* ^([a-z0-9-\.]+)\.example.org$) { set $subdomain $1; } location / { root /var/www/$subdomain; index index.html index.php; location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } } } $ docker run -d -p 80:80 -v /var/run/docker.sock: /tmp/docker.sock:ro jwilder/nginx-proxy $ docker run -e VIRTUAL_HOST=foo.example.com nginx $ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - $ sudo apt install apt-transport-https $ sudo apt update $ sudo apt install filebeat $ sudo systemctl daemon-reload $ sudo systemctl enable filebeat $ wget -c https://github.com/jwilder/docker-gen/releases/download/0.7.3/docker-gen-linux-amd64-0.7.3.tar.gz $ sudo vi /etc/systemd/system/docker-gen.service [Unit] Description=A file generator that renders templates using Docker Container meta-data. Documentation=https://github.com/jwilder/docker-gen After=network.target docker.socket Requires=docker.socket= [Service] ExecStart=/opt/docker-gen/docker-gen -notify "/etc/init.d /filebeat restart > /dev/null 2>&1 &" -notify-output -watch /etc/docker-gen/filebeat.tmpl /etc/filebeat/filebeat.yml Restart=always [Install] WantedBy=multi-user.target Alias=docker-gen.service $ sudo vi /etc/docker-gen/filebeat.tmpl filebeat.prospectors: {{ range $key, $value := . }} - paths: - /var/lib/docker/containers/{{ $value.ID }}/{{ $value.ID }}-json.log - /var/log/plugins/{{ $value.Name }}/*.log tags: ["{{ $value.Image.Repository }}"] fields: {{ if eq $value.Image.Repository "testsite" }} virtual_host: "{{ $value.Env.VIRTUAL_HOST }}" {{ end }} {{ end }} output: logstash: hosts: ['logstash.expamle.org:5044'] tls: certificate_authorities: ['/etc/ssl/logstash/logstash.crt'] ssl: enabled: true verification_mode: none supported_protocols: [SSLv3, TLSv1.0, TLSv1.1, TLSv1.2] logging: files: rotateeverybytes: 10485760 $ sudo systemctl start filebeat ----------------------------------------------------------------------------------------- Установка и настройка Yate с поддержкой H.323 в CentOS7 Вячеслав Королев # yum install flex gcc-c++ с++ make wget bison libtiff-devel mod_dav_svn subversion autoconf mysql-connector-odbc mysql-devel # cd /usr/local/src # wget http://www.h323plus.org/source/download/ptlib-2.10.1.tar.bz2 # tar -xjvf ptlib-2.10.1.tar.bz2 # cd ptlib-2.10.1 # ./configure # make && make install # cd .. # cd /usr/local/src # wget http://www.h323plus.org/source/download/h323plus-v1_23_0.tar.gz # tar -zxvf h323plus-v1_23_0.tar.gz # cd h323plus # ./configure # make && make install # cd .. # cd /usr/src # svn checkout http://voip.null.ro/svn/yate/trunk yate-SVN # cd yate-SVN # ./autogen.sh # ./configure --with-openh323=/usr/local/src/h323plus # make # make install-noapi # echo "/usr/local/lib" >> /etc/ld.so.conf # ldconfig # yate -V [general] port=5061 [codecs] default=no mulaw=yes alaw=yes [general] fallback_rtp=no [codecs] default=false mulaw=yes alaw=yes [ep] faststart=true [general] minport = 8000 maxport=32768 [100] password = 12345 [200] password = 12345 regexp=target ${paramname}regexp=target [default] ^1090$=return;called=200;callername=${callername}; caller=${caller}; [default] ^1090$=sip/sip:3737@10.10.49.150;caller=${caller}; callername=${caller} ${username}^$=-;error=noauth # cp /usr/src/yate-SVN/packing/yate.logrotate /etc/logrotate.d/yate # Have to rotate the log and CDR files before each reaches # 2GB in size /var/log/yate /var/log/yate-cdr.tsv { size=20M rotate 5 missingok sharedscripts notifempty postrotate /bin/kill -HUP `/bin/cat /var/run/yate.pid` endscript } [modules] jabberserver.yate=false jbfeatures.yate=false jabberclient.yate=false yradius.yate=false mysqldb.yate=false yjinglechan.yate=false ciscosm.yate=false mgcpca.yate=false mgcpgw.yate=false ysnmpagent.yate=false yiaxchan.yate=false # cp /usr/src/yate-SVN/packing/rpm/yate.service /etc/systemd/system/multi-user.target.wants/ # nano /etc/systemd/system/multi-user.target.wants/yate.service ExecStart=/usr/bin/yate -d -p /var/run/yate.pid $OPTS ExecStart=/usr/local/bin/yate -d -p /var/run/yate.pid $OPTS # systemctl daemon-reload # systemctl start yate.service # systemctl status yate.service # systemctl stop yate.service # telnet localhost 5038 debug on Debug level: 8, objects: off, local: on, threshold: 10 color on Colorized output: yes uptime status regfile restart now debug h323 level 10 debug sip level 10 ----------------------------------------------------------------------------------------- Планировщик задач для PHP-сайта Вячеслав Королев 0): ob_end_flush (); endwhile; flush (); /*-----------------------*/ /* Начало нового сеанса. */ /*-----------------------*/ $miniter = 30; // минимальное количество итераций $id = rand (); // идентификатор сеанса $fnsav = 'test1.sav'; // имя файла для передачи состояния между сеансами $fntxt = 'test1.txt'; // имя файла для результатов работы сценария $fnlog = 'test1.log'; // имя журнального файла Logbook ($fnlog, "#$id - start"); if (SeanceBegin ($fnsav, !(isset ($_GET['mode']) and $_GET['mode'] == 'continue'))): /*-------------------------------------------*/ /* Восстановление данных предыдущего сеанса. */ /*-------------------------------------------*/ $i = fgets ($fsav); if ($i > $miniter): die (); endif; if ($i == ''): $i = 0; endif; /*-----------------------------*/ /* Выполнение полезной работы. */ /*-----------------------------*/ $f = fopen ($fntxt, file_exists ($fntxt)? "at": "wt"); fputs ($f, "$id - Seance begin: " . time () . PHP_EOL); while (time () < $tmout): fputs ($f, "$id - $i" . PHP_EOL); sleep (1); $i++; endwhile; fputs ($f, "$id - Seance end: " . time () . PHP_EOL); fclose ($f); /*---------------------------*/ /* Сохранение данных сеанса. */ /*---------------------------*/ rewind ($fsav); fputs ($fsav, $i); SeanceEnd ($fsav); /*--------------------------------------------------------------*/ /* Завершение текущего сеанса и передача управления следующему. */ /*--------------------------------------------------------------*/ $url = "$_SERVER[REQUEST_SCHEME]://$_SERVER[HTTP_HOST] $_SERVER[PHP_SELF]?mode=continue"; Logbook ($fnlog, "#$id - pass $url."); PassControl ($url, strlen ($body), $fnlog, $id); Logbook ($fnlog, "#$id - normal shutdown."); else: Logbook ($fnlog, "#$id - can't enter critical section."); endif; /*==============================================================*/ /* Начало сеанса как критической секции кода. */ /* Вызов: $fn - имя файла для хранения данных сеанса. */ /* $first - признак первого сеанса в последовательности. */ /* Возврат: манипулятор открытого файла или */ /* FALSE в случае неудачи. */ /*==============================================================*/ function SeanceBegin ($fn, $first) { global $fsav; $res = FALSE; $fsav = fopen ($fn, file_exists ($fn)? 'r+t': 'w+t'); if ($fsav !== FALSE): if (flock ($fsav, LOCK_EX | LOCK_NB)): $res = TRUE; if ($first): ftruncate ($fsav, 0); endif; else: fclose ($fsav); endif; endif; return $res; } /*=================================================*/ /* Завершение сеанса как критической секции кода. */ /*=================================================*/ function SeanceEnd () { global $fsav; flock ($fsav, LOCK_UN); fclose ($fsav); } /*===========================================================*/ /* Передача эстафеты следующему сеансу. */ /* Вызов: $url - URL PHP-сценария для передачи эстафеты, */ /* $replylen - ожидаемая длина ответа, */ /* $fnlog - имя журнального файла, */ /* $id - идентификатор текущего сеанса. */ /* Возврат: ответ сценария, которому была передана эстафета. */ /*===========================================================*/ function PassControl ($url, $replylen, $fnlog, $id) { Logbook ($fnlog, "#$id PassControl (...) - start request"); $res = HttpRequest ($url, '1.0', 'GET', 'Connection:close', '', 10, 4); Logbook ($fnlog, "#$id PassControl (...) - request done, " . ($res===FALSE? 'ERROR': 'SUCCESS')); return $res; } /*==============================================*/ /* Получение информации по HTTP-запросу. */ /* Вызов: $url - адрес запроса, */ /* $httpver - версия протокола HTTP, */ /* $httpmeth - метод HTTP, */ /* $httpopt - опции HTTP-запроса, */ /* $httpbody - тело запроса, */ /* $maxlen - максимальный размер ответа, */ /* $timeout - таймаут в секундах. */ /* Возврат: ответ сервера или */ /* FALSE в случае ошибки. */ /*==============================================*/ function HttpRequest ($url, $httpver = '1.1', $httpmethod = 'GET', $httpopt = '', $httpbody = '', $maxlen = 4096, $timeout = 15) { global $fnlog; $res = FALSE; $urlparts = parse_url ($url); $tm = time (); /* Подготовка элементов соединения и запроса. */ $rqscheme = ($urlparts['scheme'] == 'https'? 'tls://': ''); $rqhost = $urlparts['host']; $rqport = array_key_exists ('port', $urlparts)? $urlparts['port']: ($urlparts['scheme'] == 'https'? '443': '80'); $rqpath = array_key_exists ('path', $urlparts)? $urlparts['path']: '/'; $rqquery = array_key_exists ('query', $urlparts)? "?$urlparts[query]": ''; /* Установка соединения. */ $f = @fsockopen ("$rqscheme$rqhost", $rqport, $errno, $errstr, $timeout); if ($f !== FALSE): /* Формирование заголовка запроса. */ $header[] = "$httpmethod $rqpath$rqquery HTTP/$httpver"; $header[] = "Host: $rqhost" . (array_key_exists ('port', $urlparts)? ":$urlparts[port]": ''); /* Добавление в заголовок опций запроса. */ $httpeol = "\r\n"; if (is_array ($httpopt)): $httpopt = implode ($httpeol, $httpopt); endif; if ($httpopt > ''): $header[] = $httpopt; endif; $header[] = ''; /* Формирование тела запроса. */ if (is_array ($httpbody)): $httpbody = implode ($httpeol, $httpbody); endif; if ($httpbody > ''): $header[] = $httpbody; endif; $header[] = ''; /* Сборка и отправка запроса. */ $rq = implode ($httpeol, $header); fwrite ($f, $rq); /* Приём ответа. */ $to = $timeout - (time () - $tm); if ($maxlen > 0 and $to > 0): stream_set_timeout ($f, $to); $s = fread ($f, $maxlen); while ($s !== FALSE): $res .= $s; $maxlen -= strlen ($s); $to = $timeout - (time () - $tm); if ($maxlen > 0 and $to > 0): stream_set_timeout ($f, $to); $s = fread ($f, $maxlen); else: $s = FALSE; endif; endwhile; endif; /* Анализ результата операции чтения. */ $md = stream_get_meta_data ($f); if ($md['timed_out']): $res = FALSE; endif; /* Завершение соединения. */ fclose ($f); endif; return $res; } /*=================================*/ /* Запись сообщения в журнал. */ /* Вызов: $fn - имя файла журнала, */ /* $msg - текст сообщения. */ /*=================================*/ function Logbook ($fn, $msg) { $f = fopen ($fn, file_exists ($fn)? 'at': 'wt'); if ($f !== FALSE): if (flock ($f, LOCK_EX)): $tm = time (); fputs ($f, "$tm: $msg" . PHP_EOL); flock ($f, LOCK_UN); endif; fclose ($f); endif; } ?> 0): ob_end_flush (); endwhile; flush (); ... function Gif1x1 () { return "GIF89a\x01\x00\x01\x00\xF7" . str_repeat ("\x00", 770) . "\x21\xF9\x04\x01\x00\x00\xFF\x00" . "\x2C\x00\x00\x00\x00\x01\x00\x01" . "\x00\x00\x08\x04\x00\xFF\x05\x04" . "\x00\x3B"; } ?> if ($got_rates): /* новые курсы будут завтра */ $hr = 11; $mn = 30; $res = mktime (0, 0, 0) + 60 * ($mn + 60 * (24 + $hr)); else: /* повтор после неудачи */ $res = $now + 60 * 15; endif; /* Восстановление сохраненного состояния. */ $iteration = 1 + (isset ($context['iteration'])? $context['iteration']: 0); /* Сохранение нового состояния. */ $context['iteration'] = $iteration; ----------------------------------------------------------------------------------------- Пример решения классической рекурсивной задачи итерационным способом средствами 1С Кирилл Ткаченко Процедура ПечатьДоски(доска) Перем i, s; s = ""; Для i = 0 По 7 Цикл s = s + " " + доска[i]; КонецЦикла; Сообщить(s); КонецПроцедуры Функция Abs(А) Возврат ?(А >= 0, А, -А); КонецФункции Перем доска, i, j, подАтакой; доска = Новый Массив(8); i = 1; Пока Истина Цикл … КонецЦикла; доска[i - 1] = 1; Пока Истина Цикл … КонецЦикла; подАтакой = Ложь; Если i <> 1 Тогда Для j = 1 По i - 1 Цикл Если (доска[i - 1] = доска[j - 1]) Или (Abs(доска[i - 1] - доска[j - 1]) = Abs(i - j)) Тогда подАтакой = Истина; Прервать; КонецЕсли; КонецЦикла; ИначеЕсли доска[i - 1] >= 5 Тогда Возврат; КонецЕсли; Если Не подАтакой Тогда i = i + 1; Если i <= 8 Тогда Прервать; КонецЕсли; ПечатьДоски(доска); i = 8; КонецЕсли; Пока доска[i - 1] >= 8 Цикл i = i - 1; КонецЦикла; доска[i - 1] = доска[i - 1] + 1; ----------------------------------------------------------------------------------------- Лабораторная работа: исследуем inode. Часть 1. Взаимодействие с inode через стандартные программы на пользовательском уровне Павел Закляков # dumpe2fs /dev/sda1 -h # dumpe2fs /dev/sdaX for i in $(seq 1 xxx); do touch $i; done -----------------------------------------------------------------------------------------