@INC
Привет! Меня зовут Павел, я программист.
На этой страничке предлагаю вашему вниманию набор личных
в области программирования и не только.
Помимо программирования также интересуют темы:
Я люблю систематизировать знания, для меня лично эта страничка является своеобразной базой знаний (F.A.Q) и записной книжкой. Следую принципу Эйнштейна, “зачем мне что-то запоминать, когда я могу легко посмотреть это в книге”. А ещё знания могут улучшить качество жизни.
На создание странички немного вдохновила эта https://www.reg.ru/coding_standards
Бывает что у меня спрашивают совета по тому или иному вопросу. Специально поэтому на страничке работают якорные ссылки, вместо копирования текста целиком можно скинуть прямую ссылку на соответствующий раздел
Ещё я добавил эту страничку в закладки, во многих случаях она становится отправной точкой для решения каких-то проблем. Т.к. страничка публична, вы можете сделать также ;)
Если вы увидели пустой раздел - значит он в ближайшее время точно будет наполнен.
Предлагаемый список советов не является исчерпывающим.
Исходный текст страниц написан на языке Markdown, хранится в git-репозитории и хостится на бесплатной платформе Github Pages
Постоянный адрес странички: https://pavelsr.github.io/my_coding_standarts/
Страница собирается простым генератором сайтов Jekyll, написанным на Ruby
Логика сборки простая и по сути сводится к трём строчкам кода
https://github.com/pavelsr/my_coding_standarts/tree/master/_sections
Для красоты также используются готовые opensource-библиотеки
Я с удовольствием рассмотрю все замечания и дополнения :)
Присылайте правки в формате pull request сюда
Кстати, для того чтобы предложить правки совсем не обязательно знать git, достаточно отредактировать через браузер соответствующий раздел из папки _sections и выбрать “Create a new branch for this commit and start a pull request” при сохранении изменений. Если для вас это совсем сложно - присылайте правки в свободном формате в Telegram
Идеально, если вы владеете git и можете сами посмотреть как будут выглядеть ваши правки на скомпилированной странице. Как это сделать - расписано тут
Если вы хотите сделать себе аналогичную страничку со своими гайдлайнами - заведите себе аккаунт на Github, перейдите на страничку https://github.com/pavelsr/my_coding_standarts и нажмите справа вверху кнопку “Fork”. Страничке станет доступна на https://<your_username>.github.io/my_coding_standarts/
.
За определённую плату могу также настроить такую страничку “под ключ” ;)
Вообще, на большинство вопросов уже есть ответы
Ёмко сформулируйте запрос на английском и поищите на Stackexchange - самое большое сообщество технологических экспертов
Интересные вопросы я добавляю себе в избранное, можете посмотреть там:
Также рекомендую посмотреть awesome - пользовательские списки отличных opensource инструментов
Если ваш вопрос касается конкретного устройства (телефона, 3G модема, камеры и др.) - поищите на форуме 4PDA
Если вы сисадмин, вам надо настроить какие-то железки или вы технический специалист Фаблаб - взгляните еще сюда (и вообще во все три pinned репозитория профиля)
Обязательно выучите наизусть приоритеты операций, это позволит избежать многих ошибок и упростить синтаксис. Приоритеты плюс минус одинаковы во всех языках программирования.
Смотрите эту github коллекцию https://github.com/collections/learn-to-code
А еще запомнить принип RTFM :)
Здесь собираю список дополнительного ПО (преимущественно открытого и бесплатного), которое может быть полезно при разработке и дизайне.
А также частые настройки по разграничению прав пользователей
Мои личные предпочтения как разработчика:
И конечно современные браузеры - Firefox, Opera, Яндекс.Браузер, Chrome, Ungoogled Сhrominum, Tor Browser
https://anybalance.ru/ - мобильное приложение мониторинг балансов
Note: cсылки могут быть партнёрскими :)
https://documents.kontur.ru/ - бесплатное выставление первички: счёт, акт, накладная (аналог есть в тинькофф.бизнес)
https://hrscanner.ru/ - автоматизация тестирования персонала
https://emny.ru/ - поиск сотрудников ВК, с ними работает Леруа Мерлен
Проект | Фукционал | Docker образ | LXC контейнеры |
---|---|---|---|
https://nextcloud.com/ | файловый сервер | ||
https://owncloud.org/ | файловый сервер | ||
https://goharbor.io/ | docker registry | ||
https://botpress.io | сервер для создания собственных ботов | ||
https://sentry.io/ | система агрегации ошибок | ||
https://www.freepbx.org/ | собственная SIP телефония | ||
https://phplist.com/ | email рассылки, аналог MailChimp | ||
prometheus.io | мониторинг ( аналоги: Zabbix, Nginx, Kibana ) | ||
https://opentracing.io/ | трасировщик | ||
osticket | тикетная система (аналог: OTRS, Redmine) | ||
https://www.limesurvey.org/ | опросы | ||
Odoo | CRM/ERP | ||
Zoneminder | видеонаблюдение | ||
maltego | инструмент для анализа данных | ||
docxtemplater | конструктор документов | ||
DocxJS | конструктор документов | ||
Syndesis | opensource аналог Zapier |
https://github.com/kylemanna/docker-openvpn
https://github.com/jpetazzo/dockvpn
https://bitly.com
https://git.io/
https://goo.gl - Google, с API и аналитикой
https://t.co - twitter
http://yourls.org/ - можно на свой домен, https://github.com/YOURLS/YOURLS
https://kutt.it/
Раздел для сисадминов
Особенности ОС, которые важно знать
Далее решения типичных задач конфигурирования
dmesg
systemd-analyze [critical-chain|blame]
Также можно отключить в /etc/default/grub
опции quiet splash
и посмотреть вживую что долго грузится.
Лог загрузки можно увидеть в /var/log/boot.log
Если видишь [ TIME ] Timed out waiting for device /dev/disk/by-uuid/CC01-64BD
- возможно Windows изменил UID раздела /boot/efi, рекомендуется уточнить через blkid
1) Сеть, через GUI Network manager: https://askubuntu.com/questions/894750/allow-a-guest-session-wifi-access-with-no-users-logged-in
2) Съемные носители
New user: useradd -G plugdev fablab
sudo usermod -a -G <groupName> userName
sudo usermod -a -G plugdev fablab
sudo usermod -a -G netdev fablab
Либо создать пользователя fablab-user
без пароля и добавить все эти привилегии ему
Полная инфа по привилегиям: https://wiki.ubuntu.com/Security/Privileges
sudo usermod -a -G vboxusers $USER
Посмотреть список групп пользователя можно командной groups $USER
Делаем папку виртуальной машины общей
Заходим в пользователя, оттуда запускаем команду Машина -> Добавить
P.S. Этот вариант расчитан на то, что виртуальную машину одновременно использует только один человек (вообще судя по всему VirtualBox и так сам её блокирует для запуска от других пользователей)
CTRL+WIN+SPACE
При попытке установить suldr в ubuntu 18.04 d
W: Ошибка GPG: https://www.bchemnet.com/suldr debian InRelease: Следующие подписи не могут быть проверены, так как недоступен открытый ключ: NO_PUBKEY FB510D557CC3E840
E: Репозиторий «https://www.bchemnet.com/suldr debian InRelease» не подписан.
N: Обновление из этого репозитория нельзя выполнить безопасным способом, и поэтому по умолчанию он отключён.
N: Смотрите справочную страницу apt-secure(8) о создании репозитория и настройке пользователя.
и решение, предложенное на форуме (ниже)
sudo apt-get clean # Remove cached packages
cd /var/lib/apt
sudo mv lists lists.old # Backup mirror info
sudo mkdir -p lists/partial # Recreate directory structure
sudo apt-get clean
sudo apt-get update # Fetch mirror info
не помогает
Также не помогают
sudo apt-key adv --keyserver bchemnet.com --recv-keys FB510D557CC3E840
wget http://www.bchemnet.com/suldr/pool/debian/extra/su/suldr-keyring_1_all.deb
[trusted=yes]
https://mirror.yandex.ru/mirrors/deepin/packages/pool/non-free/s/suldr-keyring/ - зеркало яндекса
sudo wget -O key.deb https://mirror.yandex.ru/mirrors/deepin/packages/pool/non-free/s/suldr-keyring/suldr-keyring_2_all.deb
sudo dpkg -i key.deb
Данный документ ставит задачу помочь быстро разобраться в чужом коде и предоставить инструменты для автоматизированного документирования
Особенно полезно если в репозитории может лежать неработающий код.
Показать summary какие расширения файлов есть в папке
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
TO-DO: показывать рядом с расширениями статистику файлов
https://stackoverflow.com/questions/1842254/how-can-i-find-all-of-the-distinct-file-extensions-in-a-folder-hierarchy
Очень удобный инструмент для документирования API - Swagger
Вначале можно инспектить API через Swagger Inspector, а уже оттуда добавлять в SwaggerHub
Вариант 1 - статический анализ.
Написал отличный хелпер для perl_call_graph
Установка:
sudo curl -L https://bit.ly/perlcghelper -o /usr/local/bin/pcg && sudo chmod +x /usr/local/bin/pcg
Вариант 2 - динамический анализ
Простой вариант - запустить стандартный дебаггер
Сложный вариант (требует запуска скрипта) - вызвать скрипт с опцией -d:NYTProf
, затем hytprofhtml и посмотреть packages-callgraph.dot. Бонус этого варианта что покажет ещё и время выполнения каждой функции
В этом разделе собрана информация о том, как написать хорошее резюме
https://sourcerer.io/ (пример - https://sourcerer.io/pavelsr)
https://github.com/github/personal-website
Some helpful scripts
Task 1. Delete all before binlog
/mysql/mysql_dbh/binlog/dbh.000371
/mysql/mysql_dbh/binlog/dbh.000372
/mysql/mysql_dbh/binlog/dbh.000373
sed 's/^.*binlog/binlog/' /diskd/litdb/mysql_dbh/binlog/dbh.index
chsh
Для портабельности рекомендую озаглавливать ваши скрипты как
Например из-за этого
#!/usr/bin/env bash
cat without comments
cat httpd.conf | egrep -v "^\s*(#|$)"
Напечатать при помощи cat
cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF
find -L -type f -name "*.json" | xargs tail -n +1
Хороший, но недостаточно, вывод:
tree
find -L -type f . -exec cat {} +
find -L -type f | xargs cat
find . -type f -printf "%p\n"
Требования к разделу: приведенные решения должны работать в любой Linux системе, даже в Busybox
sudo adduser [--home DIR] user
sudo usermod -aG docker $USER
Два варианта:
1) ssh-copy-id id@server
2) sshpass
- требует сохранения пароля в явном виде где-нить в текстовом файлике
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
sudo apt-get install clusterssh
netstat -ntulp | grep LISTEN
netstat -ntulp | grep LISTEN | grep 80
netstat -ntulp | grep LISTEN | grep VirtualBox
Глобальное решение - симлинк на нужный скрипт в $PATH
. Обычно добавляют в /usr/local/bin
или в /usr/bin
Например
sudo ln -s /full/path/to/your/file /usr/local/bin/name_of_new_command
sudo ln -s /root/certbot-auto /usr/local/bin/certbot
Для конкретного юзера - редактировать ~/.bashrc
Альтернатива - использование alias (обычно пишутся в .bash_profile
)
ln -s $(which <existing_command>) /usr/bin/<my_command>
dmesg | grep tty
sudo blkid
sudo mkdir /media/windows
Образец
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=be35a709-c787-4198-a903-d5fdc80ab2f8 /media/nas ntfs-3g auto,users,uid=1000,gid=100,dmask=027,fmask=137,utf8 0 0
sudo mount -t auto -v /dev/sdb2 /diskd
Использовать -l
и -f
опции umount
sudo badblocks -vs /dev/sdb2 > badblocks.txt
sudo nano /etc/hostname
sudo nano /etc/hosts
dig +short myip.opendns.com @resolver1.opendns.com
Топ 10 самых больших файлов
du -a / | sort -n -r | head -n 10
Либо можно вызвать GUI sudo baobab
$ hwinfo --block --short
disk:
/dev/sdb KINGSTON SHSS37A
/dev/sda Samsung SSD 850
Альтернативы:
lsblk -o name,mountpoint,label,size,fstype,uuid | egrep -v "^loop"
sudo parted -l
Настройки -> Утилиты -> Параллельные приложения
Альтернативы: сторонние средства - Parallel Space или новый пользователь
httpd -M | grep -e cgid -e alias -e env_module
Ctrl+Shift+P - Command Palette
http://atom.io/packages/copy-path удобное копирование путей
https://atom.io/packages/git-blame
https://atom.io/packages/structure-view ( плагин от Alibaba, запускается по Сtrl+O, основан на ctags )
https://atom.io/packages/symbols-view ( Генерация: ctags --language-force=Perl -R .
)
https://github.com/danielbrodin/atom-project-manager (alt-shift-P, Ctrl+Shift+P + Project Manager: Edit Projects, поддерживает всё что есть в config.cson )
C кодировкой затык т.к. эта функциональность предоставляется плагином
https://atom.io/packages/editorconfig - поддержка кросс-IDE файлов .editorconfig
Пример файла .editorconfig
:
root = true
[*.{pl,pm}]
charset = cp-1251
indent_style = space
indent_size = 4
https://atom.io/packages/atomic-management - конфигурационные файлы для проектов (не поддерживает кодировку)
https://atom.io/packages/file-templates - шаблоны файлов
В некоторых случаях рекомендую отключать системный плагин whitespace, потому что https://github.com/atom/atom/issues/4741
Показать crontab для всех пользователей
https://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users
Если вдруг вам по каким-то причинам нужно загрузить весь блокчейн эфира, но не хватает места на диске
#/bin/bash
OLD_PATH="/home/pavel/.ethereum/geth/chaindata"
NEW_PATH="/Volumes/Drive2/Ethereum/"
mkdir -p $NEW_PATH
cp -rpv $OLD_PATH $NEW_PATH
rm -rf $OLD_PATH
ln -s $NEW_PATH $OLD_PATH
or you can make an alias:
alias namecoin='namecoin -datadir=/media/nas/Namecoin'
docker run -it -v $(pwd):/botpress/data -p 3000:3000 botpress/server:v11_9_4
Рейтинг - https://cpainform.ru/networks/
Самая популярная площадка - https://cityads.com/
Еще хорошие https://actionpay.net и http://ad1.ru/
GMail: Настройки -> Расширенные -> Шаблоны ответов -> Включить
При создании нового письма добавится пункт “Шаблоны ответов” а в нём полезный пункт “Сохранить черновик как шаблон”
Be aware with 4 things in cron:
1) $ENV variables
Make your own docker-entrypoint.sh
to transfer them from user ENV
2) Home dir (don’t forget to make cd
in crontab)
3) In production environment you should use cron -f
without any tail -f
4) cronjob file must end with newline
Нюансы (что надо помнить чтоб сберечь много времени)
1) Пакет cron во всех debian-based дистрибутивах скомпилирован так что может выводить свой собственный лог ТОЛЬКО в syslog. пруф. Соответственно если речь о сборки Docker-образа то нужно обязательно включать и запускать rsyslog
Чистый лог cron (без вставок с syslog
) можно получить только подтюнив настройки syslog - /etc/rsyslog.conf
/ /etc/rsyslog.d/50-default.conf
imklog
также можно отключить за ненадобностью и генерацией лишних ошибок.
2) Запускать cron нужно с помощью systemd
. Если вместо service cron start
запустить как cron -f -L 15
то работать почему-то не будет :(
Т.е. единственно правильный CMD
будет типа такого
command:
- /bin/bash
- -c
- |
cat cronjob | crontab - && service rsyslog start && service cron start && tail -f /var/log/syslog
Лог-признак того что cron стартанул правильно:
cron_demo_4 | Jul 1 09:21:55 3673956d987a cron[33]: (CRON) INFO (pidfile fd = 3)
cron_demo_4 | Jul 1 09:21:55 3673956d987a cron[35]: (CRON) STARTUP (fork ok)
https://github.com/moby/moby/issues/19616
docker stop command attempts to stop a running container first by sending a SIGTERM signal to the root process (PID 1) in the container. If the process hasn’t exited within the timeout period a SIGKILL signal will be sent.
SYNOPSIS
cron [-f] [-l] [-L loglevel]
DESCRIPTION
cron is started automatically from /etc/init.d on entering multi-user runlevels.
OPTIONS
-f Stay in foreground mode, don't daemonize.
-l Enable LSB compliant names for /etc/cron.d files. This setting, however, does not affect the parsing of files under
/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly or /etc/cron.monthly.
-n Include the FQDN in the subject when sending mails. By default, cron will abbreviate the hostname.
-L loglevel
Tell cron what to log about jobs (errors are logged regardless of this value) as the sum of the following values:
1 will log the start of all cron jobs
2 will log the end of all cron jobs
4 will log all failed jobs (exit status != 0)
8 will log the process number of all cron jobs
The default is to log the start of all jobs (1). Logging will be disabled if levels is set to zero (0). A value of
fifteen (15) will select all options.
/ # crond --help
BusyBox v1.26.2 (2017-11-23 08:40:54 GMT) multi-call binary.
Usage: crond -fbS -l N -d N -L LOGFILE -c DIR
-f Foreground
-b Background (default)
-S Log to syslog (default)
-l N Set log level. Most verbose:0, default:8
-d N Set log level, log to stderr
-L FILE Log to FILE
-c DIR Cron dir. Default:/var/spool/cron/crontabs
Alpine linux не требует указать юзера в crontab, а Ubuntu требует
echo '* * * * * perl /root/www/insert.pl 2>&1' > /etc/crontabs/root
ln -sf /proc/1/fd/1 /var/log/syslog
curl - крайне полезный инструмент для отладки HTTP-запросов
Ниже даны примеры запросов для различных Content-type
curl -s -X PUT -H "Content-Type: application/json" -d '{"action":"test"}' https://api_user:api_pass@host:port/api/v2/some_method
Заголовок Content-Type в этом случае устанавливать не нужно
curl -s -X POST -d 'globalCity=7700000000000' http://www.220v.test/city/change/
curl -sD - -o /dev/null
curl -H "Cache-Control: no-cache"
Страничка, посвященная работе с IP камерами Xiaomi Ants. На мой взляд лучшие IP камеры на рынке по соотношению цена-качество-дизайн.
Кладём скрипт equip_test.sh
с вписанными нужными SSID и passw в корневую папку:
#WiFi setter. Created by nfs911 for 4PDA
#!/bin/sh
#################################################
wifi_name="MakerHouse"
wifi_password="fab12shenzhen"
#################################################
sed -i 's/valid1=0/valid1=1/g' /etc/ui.conf
sed -i 's/doreset=1/doreset=0/g' /etc/ui.conf
#rm /etc/wpa_supplicant.conf
#rm /home/wpa_supplicant.conf
echo "ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
network={
ssid=\""$wifi_name"\"
scan_ssid=1
proto=WPA RSN
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
psk=\""$wifi_password"\"
}" > /etc/wpa_supplicant.conf
cp /etc/wpa_supplicant.conf /home/wpa_supplicant.conf
sleep 5
#mv "/home/hd1/test/equip_test.sh" "/home/hd1/test/equip_test.sh.old"
rm "/home/hd1/test/equip
RTSP urls : rtsp://10.132.193.9/ch0.h264 (1280x738) or rtsp://10.132.193.9/ch1.h264 (low quality, 640x386)
vlc -vvv rtsp://10.132.193.9/ch1.h264 --sout="#transcode{vcodec=mp4v,vfilter=canvas{width=640,height=386}}:std{access=file,mux=mp4,dst=/data/123.mp4}"
ffmpeg -i rtsp://10.132.193.9//ch0.h264 -vcodec copy -an -bsf:v h264_mp4toannexb fl.h264
Лучшие docker-практики
Я держу в проекте три файла:
docker-compose.yml - общая конфигурация
docker-compose.override.yml - только локальные настройки
docker-compose.prod.yml - настройки продакшна
Локально всё будет запускаться стандартным docker-compose up
А на проде указываем файлы явно:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
Мало кто знает, но у docker есть встроенный DNS сервер 127.0.0.11
Может быть полезно для поиска популярных opensource проектов к какой-то сфере
https://github.com/search?q=topic%3Atable&type=Repositories
У API Github очень хорошая стартовая страничка со списком url ресурсов
https://api.github.com/
Получить все значения формы
var c = console.log($('form').serialize());
Получить конкретное значение формы по name
$('#egrn_form').find('input[name="egrn"]').val();
#!/usr/bin/env perl
https://gh.metacpan.org/ - Люди Perl или проект “GitHub меееts CPAN”
perldoc - документация, созданная разработчиками языка.
Очень рекомендую полазить по двум следующим ссылкам
https://perldoc.perl.org/perlop.html
http://perldoc.perl.org/index-tutorials.html
http://perldoc.perl.org/index-faq.html
Помимо официального браузера (сейчас в стадии beta) у perldoc есть неофициальный - https://perldoc.pl, в нём очень удобно переключаться между одной и той же документацией для разных версий perl, а также давать пермалинки на разделы
Все перловые файлы должны быть отформатированы с помощью утилиты perltidy.
Все перловые файлы должны быть написаны в соответствии с рекомендациями “Perl Best Practices”.
Самые основные гайдлайны записаны тут - https://perldoc.perl.org/perlstyle.html
Полный список pbp на русском тут, html версия тут
Автоматизированно проверить свой код на соответствие рекомендациям PBP можно при помощи perlcritic
Learn Perl in about 2 hours 30 minutes - http://qntm.org/files/perl/perl.html
http://modernperlbooks.com/
https://perl.plover.com/
https://www.youtube.com/user/gabor529/videos
https://metacpan.org/pod/POD2::RU
https://ru.perlmaven.com/
https://ebookfoundation.github.io/free-programming-books/free-programming-books-ru.html#perl
https://ivan.bessarabov.ru/blog
https://perlweekly.com/
https://stackoverflow.com/questions/1915616/how-can-i-elegantly-call-a-perl-subroutine-whose-name-is-held-in-a-variable
no warnings 'experimental::smartmatch';
ok ( "11.06.2019" ~~ @x );
Разберем один возможно неочевидный вывод при конкатенации и тернарном операторе
Пример:
my $str = '';
my $a = 'a';
$a ? $str.="b" : $str.= "c";
print $str;
Вопрос: Почему выводится bc
а не b
?
Ответ: всё просто: приоритет оператора .=
больше чем у ?:
. Получается: ($a ? $str.="b" : $str).= "c"
Правильная запись тернарного оператора должна выглядеть так:
my $days_plus = ( $dow - $dt_min->day_of_week < 0 ) ? ( 7 - $dow ) : ( $dow - $dt_min->day_of_week ) ;
For popular tasks please check Regexp::Common namespace firstly
Работа с копией - /r
use 5.14.0 ;
my $someString = "how do you do this";
say ($someString =~ s/how do/this is how/r) ;
Live replacement:
my $url =~ s/^\/board\/advertisement\/([0-9:]+)\//$1/;
Complex patterns:
my $pattern = '^\s*server_name\s*'.$hash->{server_name};
$hash->{str_from} = firstidx { $_ =~ qr/$pattern/ } @file;
Tested regexp for email:
if ($text_decoded =~ /(\w+@[\w.-]+|\{(?:\w+, *)+\w+\}@[\w.-]+)/) {
warn $1;
}
Substring until first appearance:
my $string = "hello.world";
my $substring = substr($string, 0, index($string, "."));
rindex() for reverse search
@INC
#
perl -le 'print for @INC'
perl -e "print qq(@INC)"
From perl script itself:
print $_."\n" foreach (@INC);
foreach (sort keys %ENV) {
print "$_ = $ENV{$_}\n";
}
PERL5LIB
PERL5OPT=-d
PERLDB_OPTS='NonStop frame=1'
Если включена прагма use utf8, perl хранит внутри себя кодировки в Unicode
use utf8;
...
my $x = $res->decoded_content;
utf8::encode($x); # unicode -> utf8
my $decoded = decode_json $x;
Также можно юзать другие прагмы:
use encoding "cp1251";
binmode(STDOUT, ':encoding(cp1251):bytes');
use open 'IN' => ':encoding(cp1251)', 'OUT' => ':encoding(cp1251)'
Есть ещё классные модули Deep::Encode и Data::Recursive::Encode
The @ISA
array contains a list of that class’s parent classes, if any источник
sub list {
my ($calendar, $span) = @_;
warn "".(caller(0))[3]."() : ".Dumper \@_; # return a list, $calendar - first element, $span second
my $a = [ 1, 2, 3 ];
warn $#$a;
delete оставляет undef на месте элемента, a splice удаляет со смещением
https://metacpan.org/pod/Sort::HashKeys
https://metacpan.org/pod/Hash::Ordered
https://metacpan.org/pod/Hash::Flatten - может быть полезно для мультиразмерных хешей
Оставить только определённые поля
for my $i (@$part_groups) {
for my $k ( keys %$i ) {
delete $i->{$k} if !grep { $k eq $_ } qw/node_id lev2 lev2_title/;
}
}
for my $j (@$objects) {
$j = { map { $_ => $j->{$_} } grep { exists $j->{$_} } @{$jsonconfig->{tickets}{fields_to_leave}} };
}
Рекомендую использовать модули Cwd и File::Spec
Примеры:
use Cwd 'abs_path';
use File::Spec;
warn abs_path('this.pl');
warn abs_path(__FILE__);
warn abs_path('a/this.pl'); # doesn't work
use Cwd;
warn getcwd();
warn File::Spec->catfile(getcwd(), 'html/regexp_test_1.html'); # get abs path
Хорошее решение - использование File::Slurp
use File::Slurp qw(read_file);
my $text = read_file($url) ;
Вариант 1. Передача через конструктор объекта, ->new().
Вариант 2. Передача через параметры use, дальнейшая обработка через функцию import. Функция use обязательно вызывает import
use MyApp prm1 => 'x';
...
package MyApp;
use Data::Dumper;
sub import {
print "This method will be executed anyway\n";
my $pkg = shift;
warn Dumper \@_; # [ 'prm1', 'x' ];
}
Примеры: Log::Any::Adpater,
Внимание: если хотите сохранить структуру хеша, передавайте как hashref
Вариант 3. Через обязательный вызов какого-либо метода
use MyApp; my $p = MyApp->new; $p->configure
Вариант 4. Через переопределение глобальных переменных модуля. $Data::Dumper::Indent
https://pause.perl.org/pause/query?ACTION=pause_namingmodules
Вначале посмотреть среди core modules: https://perldoc.perl.org/index-modules-A.html
Также можно воспользоваться моим сервисом, который дает возможность сортировать модули по рейтингу: https://github.com/pavelsr/cpanratings-cmp ( источник данных : https://cpanratings.perl.org/csv/all_ratings.csv )
sudo cpm install -gv App::scan_prereqs_cpanfile
# then run scan-prereqs-cpanfile
scan-prereqs-cpanfile > cpanfile
sudo cpanm --installdeps .
В общем случае: prove -lr
с Переопределение функций в тестах
local *LWP::UserAgent::post = sub { ( undef, $url, %params ) = @_; return $resp };
Вариант переопределения через GOTO если данные внутри переопределения не нужны
my $z = \&LWP::UserAgent::get;
*Text::Tmpl2::render = sub {
...
goto &$z;
};
Using Devel::Cover
Example from Makefile:
docker-cover:
docker exec zone cover -test -silent -nogcov -make 'prove -l $(file)' -report html
docker-cover-all:
docker exec zone cover -test -silent -nogcov -report json
Есть модули, которые упростят задачу
https://metacpan.org/pod/App::Cmd
https://metacpan.org/pod/App::CLI::Command
#!/usr/bin/env perl
use strict;
use warnings;
print "Content-type: text/html\n\n";
foreach my $key (keys %ENV) {
print "$key --> $ENV{$key}<br>";
}
Вывод версии Perl:
print "Content-type: text/html\n\n";
print $^V;
Извлечение списка схем:
$dbh->tables('', '%', '');
Список таблиц в текущей схеме
@t = $dbh->tables(); # с префиксом
Если нужно значения только одной колонки
$dbh->selectcol_arrayref('SELECT node_id FROM Ru_Node ORDER BY node_id');
@result = @{ $dbh->selectall_arrayref($sql, { Slice => {} }) };
Использование SQL::Abstract с DBI
my $table = 'cities';
my $sql = SQL::Abstract->new;
my $query = { code => 'LED' };
my ($stmt, @bind) = $sql->select($table, [ qw/code name country_code/ ], $query);
my $sth = $dbh->prepare($stmt);
$sth->execute(@bind);
warn Dumper $sth->fetchall_arrayref( {} ); # as AoH, with hash Slice
$sth->execute(@bind);
warn Dumper $sth->fetchall_hashref('code'); # as HoH
При помощи https://metacpan.org/pod/DBI#Catalog-Methods пока нельзя получить инфо о количестве записей, только так:
my $count = $conn->selectrow_array("SELECT COUNT(*) FROM $table");
$sth = $dbh->table_info( $catalog, $schema, $table, $type );
# $catalog - нужно оставить пустой строкой
# $schema - если пустая то текущая база, если нет то будут включены еще и другие бд, например information_schema
sub _insert_hash {
my ( $self, $table, $field_values ) = @_;
# return if !defined $field_values;
return if (!%$field_values);
my @fields = sort keys %$field_values;
my @values = @{$field_values}{@fields};
my $sql = sprintf "insert into %s (%s) values (%s)", $table, join( ",", @fields ), join( ",", ("?") x @fields );
# my $sth = $dbh->prepare_cached($sql);
my $sth = $self->{dbh}->prepare($sql);
return $sth->execute(@values);
}
```
1) Для логгирования рекомендуется использовать синглтон Log::Any и Log::Any::Adapter::Fille
(последний особенно удобен если одновременно в лог могут писать несколько cron скриптов - по PID можно легко понять какой именно пишет)
2) Log::Any::Adapter
может быть только один
3) Чтобы в логе показывались print
, warn
и die
из модулей нужно STDOUT и STDERR перенаправлять в тот же файл что и задан в Log::Any::Adapter::Fille
. Log::Any::Adapter::Fil(l)e
их автоматически не перехватывают!
В случае локальных игр с докером (не на продакшене) можно делать так
# perl
* * * * * cd /app && perl -Ilib crawler.pl >>/proc/1/fd/1 2>&1
#
use Log::Any::Adapter ( 'Fille', file => '/proc/1/fd/1', log_level => 'debug' );
P.S. use Log::Any::For::Std;
чет не работает.
# не перехватывает warn и die
# use Log::Any::Adapter;
# use Log::Any::For::Std;
# Log::Any::Adapter->set('Fille', file => '/app/some.log', log_level => 'debug');
Примеры отправки POST запросов при помощи LWP::UserAgent
JSON, как тут https://htaccess.madewithlove.be/api/docs
my $req = HTTP::Request->new( 'POST', 'https://htaccess.madewithlove.be/api/docs' );
$req->header( 'Content-Type' => 'application/json' );
$req->content( encode_json $content[0] );
my $response = $lwp->request($req);
print $response->decoded_content;
GET c параметрами и декодирование JSON (на примере API Яндекс.Расписаний)
use strict;
use warnings;
use LWP::UserAgent ();
use JSON;
use Data::Dumper::AutoEncode;
my $ua = LWP::UserAgent->new(timeout => 10);
my %params = (
from => 'c39',
to => 'c2',
format => 'json',
apikey => '366a6609-cf86-43a5-8e61-05c67c752ec4',
lang => 'ru_RU',
date => '2019-05-25'
);
my $url = URI->new("https://api.rasp.yandex.net/v3.0/search/");
$url->query_form(%params);
my $response = $ua->get($url); # HTTP::Response
if ($response->is_success) {
my $h = decode_json( $response->decoded_content);
warn eDumper $h;
}
else {
die $response->content;
}
Don’t Reinvent Wheel — Не переизобретайте колесо
Не переизобретайте колесо — если подобное колесо уже существует, просто адаптируйте его для своих нужд. Вероятно, для решения данной проблемы уже существует стандартный модуль в дистрибутиве Perl, или модуль из CPAN, или модуль, разработанный другими людьми внутри организации.
Список самых популярных модулей - https://metacpan.org/favorite/leaderboard
http://ali.as/top100/index.html - проект CPAN TOP 100 от Adam Kennedy.
Здесь есть четыре рейтинга
1) модули с наибольшим числом зависимостей (Heavy 100)
2) модули от которых зависят больше всех модулей (Valatile 100)
3) самые “падающие” при установке модули по данным с cpantesters.org (Fail 100)
4) (Meta 100)
http://neilb.org/reviews/index.html - обзоры на модули со сходным функционалом
TODO: предложить на обзор Neil Bowers или сделать обзор
URI::Encode::uri_decode
vs URI::Escape::uri_unescape
Mojo::DOM
vs XML::LibXML
https://metacpan.org/release/Minilla
https://metacpan.org/pod/Dist::Zilla
Mojo::DOM
#
Simulate http requests
use File::Slurp qw(read_file);
my $text = read_file($url) ;
my $dom = Mojo::DOM->new($text);
# Mojo::Message::Response -> Mojo::DOM
my $dom = $c->ua->get('https://rosreestr.net/kadastr/'.$egrn)->res->dom;
CORS
$c->res->headers->access_control_allow_origin('*');
Тест Mojolicius::Lite
# How to test Mojo::Lite apps
# https://groups.google.com/d/msg/mojolicious/-AL3SpkAwu8/gN0feyzS0_8J
use FindBin;
$ENV{MOJO_HOME} = "$FindBin::Bin/../";
require "$ENV{MOJO_HOME}/backruptcy_api.pl";
Сериализация и обработка параметров
my $param_names = $self->req->params->names
for ( allowed_object_query_properties() ) {
$query->{$_} = $c->param($_) if ( defined $c->param($_) );
}
my $query = $c->req->params->to_hash
https://perldoc.perl.org/perlootut.html RUS
https://perldoc.perl.org/perlobj.html
Moose
http://modernperlbooks.com/books/modern_perl_2016/07-object-oriented-perl.html
https://metacpan.org/pod/distribution/Moose/lib/Moose/Cookbook.pod
https://metacpan.org/pod/distribution/Moose/lib/Moose/Manual/Attributes.pod
Moo
https://perlmaven.com/oop-with-moo
Если нужны данные только из одной конкретной колонки - используйте get_column;
Пример:
my @curr_cities = map { $_->city_code } $resultset->search( {}, { select => 'city_code' } );
лучше заменить на
my @curr_cities = $resultset->get_column('city_code')->all;
Пример:
for my $city_code (@to_insert) {
$resultset->create( { city_code => $city_code } );
}
лучше заменить на
$resultset->populate([[qw(city_code)], map {[$_]} @to_insert);
Если вам нужно удалить массив записей по значениям - упростите запись за счёт модификатора -in
Пример:
for my $city_code (@to_delete) {
$resultset->search( { city_code => $city_code } )->delete_all;
}
лучше заменить на
$resultset->search({city_code => {-in => \@to_delete}})->delete()
Если будет OR - значение будет массив Если будет AND - значние хеш
https://metacpan.org/pod/DBIx::Class::ResultSet
https://metacpan.org/pod/DBIx::Class::ResultSet#ATTRIBUTES
https://metacpan.org/pod/distribution/DBIx-Class/lib/DBIx/Class/Manual/Cookbook.pod#SEARCHING
https://metacpan.org/pod/SQL::Abstract#WHERE-CLAUSES
https://metacpan.org/pod/distribution/DBIx-Class/lib/DBIx/Class/Manual/Cookbook.pod#Using-SQL-functions-on-the-left-hand-side-of-a-comparison
WHERE ID >= x
->search_rs({ id => { '>=', $ARGV[0] }});
WHERE status = ? OR status = ? OR status = ?
status => { '=', ['assigned', 'in-progress', 'pending'] };
UPDATE
Если один аргумент
$order->extra_json($extra_json);
$order->update();
Если несколько
$order->update({ extra_json => $extra_json })
Для специальных функций
my %where = ( -and => [
foo => 1234,
\["EXISTS ($sub_stmt)" => @sub_bind],
]);
mojo generate lite_app app.pl
Можно из docker-контейнера
use Mojo::mysql;
# и прописываем его в конфиге
plugin Yancy => {
backend => { Mysql => Mojo::mysql->new( 'mysql://crm:r0v@127.0.0.1/yancy' ) },
read_schema => 1,
};
morbo app.pl
Появляется роут http://127.0.0.1:3000/yancy где поднимается простейший интерфейс администрирования БД
На роуте http://127.0.0.1:3000/yancy/api появится сгенерированная схема API, которую можно использовать в Swagger
const ui = SwaggerUIBundle({
urls: [
{name: "Yancy API", url: "/yancy/api"},
],
x-list-columns
может быть как обычным массивом, так и массивом хешей со свойствами title и template
https://metacpan.org/dist/Yancy/view/lib/Yancy/Guides/Schema.pod#Configuring-the-List-View
Прописать в конфиге параметр schema.<table_name>.title
Пример:
schema:
flights:
cities_iata:
title: IATA коды городов
Задать x-list-columns в schema.<table_name>
Пример:
plugin Yancy => {
...
schema => {
companies => {
'x-list-columns' => [ 'name', 'jobs_count', 'hh_id' ]
},
},
};
(при описании схемы в json/yaml то же самое)
Cейчас отображаются по умолчанию только поля 'id', 'name', 'username', 'title', or 'slug'.
Задать что ещё отображать в админке и в каком формате можно при помощи x-list-columns
Примеры:
schema:
flights:
x-list-columns:
- flight_date
- flight_num
cities_iata:
title: IATA коды городов
example:
name: Санкт-Петербург
iata: LED
x-list-columns:
- title: Город
template: '{name} ({iata})'
Рекомендуется использовать зарядку на 2.5А и AWG20 USB cable
dd bs=4M if=2017-04-10-raspbian-jessie.img of=/dev/sdX
C progress bar:
pv -tpreb | dd bs=4M if=2017-04-10-raspbian-jessie.img of=/dev/sdX
Через pipe
unzip -p 2017-01-11-raspbian-jessie.zip | pv -tpreb | sudo dd of=/dev/null bs=64M
dcfldd:
sudo dcfldd if=Armbian_5.25_Lamobo-r1_Ubuntu_xenial_default_3.4.113.img of=/dev/sdc bs=64M
GUI:
https://etcher.io/
Прежде чем пробовать другой образ
Любой образ запустить не получится,только для архитектуры ARM. Базовые образы можно найти на:
https://hub.docker.com/r/resin (единственный образ с работающей из коробки wiringpi)
https://hub.docker.com/r/armhf/ (old)
https://hub.docker.com/u/arm32v6/
https://github.com/alexellis/docker-arm
sudo apt-get -y install python-pip
sudo pip install docker-compose
По умолчанию ssh на Raspberry Pi выключен
В разделе boot сделать sudo touch ssh
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="MYSSID"
#psk="passphrase"
psk=59e0d07fa4c7741797a4e394f38a5c321e3bed51d54ad5fcbd3f84bc7415d73d
}
Можно например через qemu
. Примерная пошаговая инструкция
Чтобы vpn подключался автоматически нужно ovpn файл положить в /etc/openvpn
Raspberry Pi, Banana Pi, Orange Pi, BeagleBone и т.д.
config wifi-device 'radio0'
option type 'mac80211'
option channel '11'
option hwmode '11g'
option path 'platform/soc/3f300000.mmc/mmc_host/mmc1/mmc1:0001/mmc1:0001:1'
option htmode 'HT20'
config wifi-iface 'default_radio0'
option device 'radio0'
option network 'lan'
option mode 'ap'
option ssid 'OpenWrt'
option encryption 'none'
Пошаговая инструкция как сделать свой кастомный образ для Raspberry PI из дистрибутива Raspbian
Let’s learn how to modify Raspbian image.
We will make 5 things
Fistly you need to know what is the start block of target filesystem and what is the block size.
So offset will be = <block_size>*<start_lba>
pavel@pavel-desktop-x79:/media/pavel/X79-NAS/torrent$ fdisk -l rpi_fablab.img
Диск rpi_fablab.img: 1,7 GiB, 1854590976 байтов, 3622248 секторов
Единицы измерения: секторов из 1 * 512 = 512 байтов
Размер сектора (логический/физический): 512 байт / 512 байт
I/O size (minimum/optimal): 512 bytes / 512 bytes
Тип метки диска: dos
Идентификатор диска: 0x11eccc69
Устр-во Загрузочный Start Конец Секторы Size Id Тип
rpi_fablab.img1 8192 93813 85622 41,8M c W95 FAT32 (LBA)
rpi_fablab.img2 94208 3622247 3528040 1,7G 83 Linux
In our example offset is 48234496
So we can mount filesystem following way
sudo mkdir -p /mnt/rpi_fablab
sudo mount -o loop,offset=48234496 rpi_fablab.img /mnt/rpi_fablab
Most used packets which are not included in distro:
SSH was disabled by default in Raspbian versions released after November 2016
If you want to enable SSH, all you need to do is to put a file called ssh in the /boot/
directory (sudo touch ssh
). The contents of the file don’t matter: it can contain any text you like, or even nothing at all. When the Pi boots, it looks for this file; if it finds it, it enables SSH and then deletes the file. Source
You can put all known SSIDs and its passwords on /mnt/rpi_fablab/etc/wpa_supplicant/wpa_supplicant.conf
file.
country=RU
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="MakerHouse"
psk="fab12shenzhen"
}
network={
ssid="MYFABLAB"
psk="fab17chile"
}
Fastest way is to execute passwd
on step 2.
Also you can build fully customized image using pi-gen script https://github.com/RPi-Distro/pi-gen
And you can even build OS image using app of my friend Denis https://cusdeb.com/
Best way is to run with Docker and docker-compose using official image
docker-compose up
But for now issue with official image still haven’t resolved, so I used bitnami image.
docker-compose.yml:
version: '2'
services:
mariadb:
image: 'bitnami/mariadb:latest'
environment:
- ALLOW_EMPTY_PASSWORD=yes
volumes:
- '${PWD}/mariadb_data:/bitnami/mariadb'
redmine:
image: 'bitnami/redmine:latest'
ports:
- '80:3000'
volumes:
- '${PWD}/redmine_data:/bitnami/redmine'
depends_on:
- mariadb
volumes:
mariadb_data:
driver: local
redmine_data:
driver: local
Below is the script which makes backup of redmine database into directory where it runs
# run it like ./backup-redmine.sh /home/redmine.fablab61.ru
parse_config_yml() {
cd $1/config
echo "Extracting database data from $1/config/database.yml"
USER=$(grep -R "username:" database.yml | grep -o -E "\b(\w+)$")
PASSWORD=$(grep -R "password:" database.yml | grep -o -E '"\b(\w+)"$' | sed -e 's/^"//' -e 's/"$//')
DB=$(grep -R "database:" database.yml | grep -o -E "\b(\w+)$")
HOST=$(grep -R "host:" database.yml | grep -o -E "\b(\w+)$")
echo "USER $USER PASS $PASSWORD DB $DB HOST $HOST"
}
PATH_TO_BACKUP=$(pwd)
if [ $# -eq 0 ]
then
echo "No arguments supplied. Plese provide abs path to redmine root directory"
else
parse_config_yml $1
echo "Start making dump"
mysqldump -u $USER -p$PASSWORD $DB > $PATH_TO_BACKUP/redmine-master_$(date +%Y%m%d_%H%M%S).data.sql
fi
Then download it from local server using scp (ssh key must be added):
scp root@fablab61.ru:/root/backups/redmine-master_20170403_231118.data.sql data.sql
It’s better to download database backup once into redmine database shared docker volume (mariadb_data
folder in our case)
Then connect to running container:
docker exec -t -i redmine_mariadb_1 /bin/bash
Then import database data:
mysql -u <username> -p<PlainPassword> <databasename> < <filename.sql>
E.g.
mysql bitnami_redmine < data.sql
Then copy all your redmine data (conf
, files
, plugins
, public/plugin_assets
and public/themes
folders):
mkdir old_redmine_data
scp -r root@fablab61.ru:/home/redmine.fablab61.ru/plugins .
scp -r root@fablab61.ru:/home/redmine.fablab61.ru/files .
scp -r root@fablab61.ru:/home/redmine.fablab61.ru/public/plugin_assets public/plugin_assets
scp -r root@fablab61.ru:/home/redmine.fablab61.ru/public/themes public/themes
In our case there was two plugins: redmine_contacts
and redmine_helpdesk
tail -f /opt/bitnami/redmine/logs/production.log
[Client 1-4] Cannot checkout session because a spawning error occurred. The identifier of the error is 12747994. Please see earlier logs for details about the error
Данный раздел посвящен выполнению задач по расписанию
ubuntu
# at -f test.sh now + 1 minute
Can't open /var/run/atd.pid to signal atd. No atd running?
alpine
Добавлять задания at
можно только на том контейнере(ос) где запущен atd
!
# at -m -f v.pl now + 1 minute
warning: commands will be executed using /bin/sh
Cannot open lockfile /var/spool/atd/.SEQ: No such file or directory
curl -X POST 'http://selenoid:4444/wd/hub/session' -d '{ "desiredCapabilities":{ "browserName":"firefox", "enableVNC":true } }'
Cоветы по проектированию таблиц и нормализации:
http://hitechnotes.blogspot.com/2014/05/blog-post.html?q=mysql
http://b62.tripod.com/doc/dbbase.htm
Помнить что есть три уровня нормализации!
Не рекомендуется обзывать колонки также как и ключевые слова
https://dev.mysql.com/doc/refman/8.0/en/keywords.html
AUTO_INCREMENT поле в таблице может быть всего одно и оно обязательно должно быть PRIMARY_KEY
there can be only one auto column and it must be defined as a key
Поэтому создать такую таблицу не получится:
CREATE TABLE checks (
id INT NOT NULL AUTO_INCREMENT COMMENT 'ID проверки',
epoch int(11) NOT NULL PRIMARY KEY COMMENT 'current unix epoch timestamp',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci, COMMENT='Все cron проверки';
Because MariaDB uses the C escape syntax in strings (for example, “\n” to represent the newline character), you must double any “" that you use in your REGEXP strings.
Two backslash characters, (one for the MariaDB parser, one for the regex library), are required to properly escape a character
Посмотреть compiled defaults:
mysqld --verbose --help
Список всех переменных смотреть тут же или в https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
с рестартом
[mysqld]
general_log = on
general_log_file=/usr/log/general.log
без рестарта
SET global log_output = 'FILE';
SET global general_log_file='/Applications/MAMP/logs/mysql_general.log';
SET global general_log = 1;
Вариант 1:
export MYSQL_PWD=${PASSWORD}; mysql
Вариант 2:
mysql_config_editor
Если вас не устраивает polling и вам нужны хуки - триггеры отличный способ
Так например если вам нужно выполнить внешний скрипты при обновлении какой-либо таблицы - смотрите на https://github.com/mysqludf/lib_mysqludf_sys
Весь список udf
https://github.com/mysqludf
Минус триггеров - не удовлетворяют критериям транзакционности ACID
select sum(case when table_comment <> '' then 1 else 0 end) / count(*)
from INFORMATION_SCHEMA.TABLES
select
concat(table_name, '.', column_name) as 'foreign key',
concat(referenced_table_name, '.', referenced_column_name) as 'references'
from
information_schema.key_column_usage
where
referenced_table_name is not null;
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('lev2','ColumnB')
AND TABLE_SCHEMA='220_volt';
Например, искомый тип - INT(10) UNSIGNED
SELECT table_schema, table_name, column_name, column_comment
FROM information_schema.columns
WHERE column_type = 'INT(10) UNSIGNED' AND column_name = 'id' AND COLUMN_KEY = 'PRI';
Очень полезно при реверс-инжиниринге базы, когда разработчики базы забыли прописать FOREIGN KEY. Например в какой-нить табличке есть поле external_id, но для него не прописан foreign key, хотя фактически он есть.
Если искомый VIEW - catalog_product, то
SHOW CREATE TABLE catalog_product;
SHOW CREATE VIEW catalog_product
SHOW FULL COLUMNS FROM <tablename>
Все комментарии к таблицам - SELECT table_comment FROM INFORMATION_SCHEMA.TABLES;
Все непустые комментарии к таблицам - SELECT table_comment FROM INFORMATION_SCHEMA.TABLES WHERE table_comment <> '';
Процент откомментированных таблиц - TODO
SELECT DISTINCT
TR.id,
R.title,
COUNT(N.node_id) PartsCount
FROM Ru_T3_Parts AS parts
INNER JOIN Ru_T3_C AS C ON (parts.code=C.code)
INNER JOIN Ru_T3_A AS A ON (A.r_id=C.r_id AND A.set_b1<=1)
INNER JOIN Ru_T3_Ref1 AS TR ON (A.r_id=TR.r_id)
INNER JOIN Ru_Ref1 AS R ON (TR.id=R.id)
INNER JOIN Ru_Node AS N ON (N.node_id=A.node_id)
LEFT JOIN Ru_T3_Status AS S_major ON (C.code=S_major.code AND S_major.region='61')
LEFT JOIN Ru_T3_Status AS S_extra ON (C.code=S_extra.code AND S_extra.region='0')
WHERE
N.lev2 = '654'
AND (S_major.status > 0 OR S_extra.status > 0)
HAVING PartsCount > 0
ORDER BY
R.title
SELECT node_length_a1, count(*) C GROUP BY node_length_a1 ORDER BY C ASC;
HAVING используется с аггрегатными операциями
WHERE before GROUP BY and HAVING after GROUP BY
https://stackoverflow.com/questions/13634369/mysql-workbench-shows-results-as-blob
https://httpbin.org/
http://slowwly.robertomurray.co.uk/
https://httpstat.us/
Чтоб использовать установленную Windows через VirtualBox с Linux хоста нужно сделать rawdisk :
VBoxManage internalcommands createrawvmdk -filename /home/$USER/sdb.vmdk -rawdisk /dev/sda2
Подробности: http://hitechnotes.blogspot.com/2012/07/blog-post.html?q=virtualbox
wp option update home 'http://newdomain.tech'
wp option update siteurl 'http://newdomain.tech'.
Если в вашем блоге включем режим Multisite, то нужно изменить в БД Wordpress в таблицах wp_site и wp_blogs соответствующие ссылки на сайт.
Вывести значение из SQL SELECT
<xmp><xsl:value-of select="@use_proxy_default" /></xmp>