Recently in Полезное Category

Phing, запрос перед выполнением

Изобретая очередной костыль, сирчеь deploy-конфиг, выпилил базу данных и конфиги с рабочего проекта.
Благо предыдущий таск бэкапил все и вся. Теперь буду осторожнее и напишу таск, который спрашивает, уверен ли я в том, что делаю.
Собственно вот:
<target name="test">
    <!-- propertyname есть аргмент arg1, с которым идет сравнение в equals -->
        <input propertyname="confirm" defaultValue="no" validargs="yes,no">This action will erase the database. Are you sure? </input>
        <if>
            <equals arg1="${confirm}" arg2="yes" />
            <then>
                <!-- Последовательно вызываем нужные таски, как если бы использовали depends-->
                <phingcall target="clean" />
                <phingcall target="composer" />
                <phingcall target="db" />
                <phingcall target="migrate" />
            </then>
            <else>
                <!-- Иначе прерываем исполнение -->
                <echo>Execution stopped</echo>
            </else>
        </if>
    </target>
Теперь Phing попробует разубедить нас в нашей правоте, тем самым экономя вазелин разнородного начальства.

Убираем "No valid subscription" в Proxmox 3.3

Proxmox это прекрасно. Но на подписку пока нет финансов, а просьба "подписаться" на этапе настройки несколько утомляет. В сети есть патч для 3.2, но он не подойдет.

Лечится это вот таким патчем:

--- /usr/share/pve-manager/ext4/pvemanagerlib.js.orig   2014-09-08 12:32:15.000000000 +0400
+++ /usr/share/pve-manager/ext4/pvemanagerlib.js        2015-03-23 02:53:46.000000000 +0400
@@ -458,23 +458,7 @@
            },
            success: function(response, opts) {
                var data = response.result.data;
-
-               if (data.status !== 'Active') {
-                   Ext.Msg.show({
-                       title: gettext('No valid subscription'),
-                       icon: Ext.Msg.WARNING,
-                       msg: PVE.Utils.noSubKeyHtml,
-                       buttons: Ext.Msg.OK,
-                       callback: function(btn) {
-                           if (btn !== 'ok') {
-                               return;
-                           }
-                           orig_cmd();
-                       }
-                   });
-               } else {
-                   orig_cmd();
-               }
+               orig_cmd();
            }
        });
     },

Включение IPv6 в Proxmox

Разжился IPv6 подсетью. Это удобно. Встала задача выпускать OpenVZ/KVM контейнеры в мир по v6. Обычно для этой операции хватает одного radvd. В Proxmox он по умолчанию отключен. И включить его надо до загрузки radvd. Либо libhands.so сегфолтится, либо еще какая причина, но modprobe мне не помог.

Включается оно так:

echo ipv6 >> /etc/modules
echo net.ipv6.conf.all.forwarding=1 >> /etc/sysctl.d/ipv6.conf

После таких манипуляций radvd не будет возмущаться на отключенный v6-форвардинг.


Phing, cron task

Есть такая штука как Phing. Это как Ant только Phing.
Позволяет совершать тривиальные задачи по развертыванию проекта на сервере, как то: настройка прав доступа к директориям/файлам, копирование чего то куда то, миграции и т.д. Но вот с заданиями для cron там беда.
Существующие, легко нагугливаемые примеры предлагают писать задания в /etc/cron.d/, куда на обычном shared-хостинге мы естественно не имеем доступа. Ну или предлагают нам sudo, что тоже слегка не то.

Но есть task exec!
Итак:
$ touch build.xml
$ nano build.xml
Приведем наш build к следующему виду:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Phing build config -->
<project name="test" basedir="." default="deploy">
    <target name="set_crontab" description="Set Crontab">
        <exec
            command='/bin/echo -en "`crontab -l 2>/dev/null`\n0 * * * *  php `pwd`/protected/yiic update\n\n" | crontab - 2>/dev/null'
            passthru="true" checkreturn="true" />
    </target>
    
    <!-- Default target -->
    <target name="deploy" depends="set_crontab"></target>
</project>
Запустим phing и увидим нечто такое:
$ phing
Buildfile: /home/vagrant/build.xml

test > set_crontab:


test > deploy:


BUILD FINISHED

Total time: 0.0925 seconds
Выполнится буквально следующий код:
/bin/echo -en "`crontab -l 2>/dev/null`\n0 * * * *  php `pwd`/protected/yiic update\n\n" | crontab - 2>/dev/null
Сказав в той же консоли 'crontab -l' увидим нечто такое:
$ crontab -l

0 * * * *  php /home/vagrant/protected/yiic update
Congratulations!

Прогрессбар для MySQL

Вот тут мы попросили dd говорить о прогрессе действий, и поняли, что это хорошо. Давайте попросим то же самое сделать и MySQL.

Заливаем дамп из файла:
pv -n dump.sql | mysql -u user -ppassword database
Вариант с zcat (можно заливать дампы в *.gz архивах):
zcat dump.sql.gz | pv -cN zcat | mysql -u user -ppassword database
И рюшечки, куда же без них:
(pv -n dump.sql | mysql -u user -ppassword database) 2>&1 | dialog --gauge "Restore database, please wait..." 10 70 0

Запрет доступа к protected и Gii.

Продолжаем есть любимый кактус, который lighttpd. В Yii есть места, куда не надо ходить по http, как то protected, в котором живет код проекта, Gii, который хоть и защищен паролем и доступом по ip, но как говорится, нечего там делать.

Включаем mod_access:
nek@phoenix:~$ sudo lighttpd-enable-mod access
Добавляем в конфиг виртуального хоста строку:
url.access-deny = ( "~", "protected", "gii")
Перезагружаем сервер:
nek@phoenix:~$ sudo service lighttpd restart

Удобная подсказка для crontab

Так часто приходится лазить в crontab из консоли, что уже забываю формат времени для него. Нашел вот такую удобную подсказку, вставил в crontab, пусть будет.
# +---------------- minute (0 - 59)
# |  +------------- hour (0 - 23)
# |  |  +---------- day of month (1 - 31)
# |  |  |  +------- month (1 - 12)
# |  |  |  |  +---- day of week (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  *  command to be executed

Skype через Proxy Squid

Встала задача выпустить Skype в сеть, не выпуская туда все остальное. Доступ в Интернет ограничен на шлюзе. Там же и будем городить прокси для Skype.
Ставим Squid:
apt-get install squid
Минимальный конфиг, на котором это взлетело:
# Адрес и порт Squid 
http_port 192.168.1.100:3128
# Лог доступа
access_log /var/log/squid/access.log squid

# Настройки кеша
cache_mem 256 MB
maximum_object_size_in_memory 512 KB

# Программа для авторизации клиентов (basic авторизация)
auth_param basic program /usr/lib/squid/ncsa_auth /etc/squid/passwd
# Путь до файла с логинами/паролями
acl passwd proxy_auth "/etc/squid/passwd"

# Списки доступа
acl all src 0.0.0.0/0

# Пускать только https
acl SSL_ports port 443 563
acl CONNECT method CONNECT

# Без этого Skype чувствует себя совсем плохо и не проходит авторизацию на Proxy
acl numeric_IPs dstdom_regex ^(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|(\[([0-9af]+)?:([0-9af:]+)?:([0-9af]+)?\])):443
acl Skype_UA browser ^skype

http_access allow passwd
http_access allow CONNECT all numeric_IPS Skype_UA SSL_ports
http_access deny CONNECT !SSL_ports

# Отключаем кеш
cache deny all
cache_dir null /tmp
Добавляем пользователей:
htpasswd -c /etc/squid/passwd username
Перезапускаем Squid:
/etc/init.d/squid restart
В Skype идем по пути Инструменты -> Настройки -> Дополнительно -> Соединение и вводим данные для доступа к Proxy.

Закачиваем файлы удобно

Достало до дрожи юзать screen+wget для каких то закачек. Захотелось чего то гуевого, но без DM. Будем юзать Aria2 и web-гуй к нему.

Ставим:
apt-get install aria2
"Демонизируем", т.к. из коробки он не работает как сервис:
touch /etc/init.d/aria2c
chmod +x /etc/init.d/aria2c
nano /etc/init.d/aria2c
Собственно сам debian-like init-скрипт:
#!/bin/sh
### BEGIN INIT INFO
# Provides:  Aria2
# Required-Start:$network $local_fs $remote_fs
# Required-Stop::$network $local_fs $remote_fs
# Should-Start:  $all
# Should-Stop:   $all
# Default-Start: 2 3 4 5
# Default-Stop:  0 1 6
# Short-Description: Aria2 - Download Manager
### END INIT INFO

NAME=aria2c
ARIA2C=/usr/bin/$NAME
PIDFILE=/var/run/$NAME.pid
CONF=/etc/aria2c.conf
USER=nobody
ARGS="--enable-rpc --rpc-listen-all --conf-path=${CONF}"

test -f $ARIA2C || exit 0

. /lib/lsb/init-functions

case "$1" in
  start)
        log_daemon_msg "Starting aria2c"
        start-stop-daemon --start --quiet -b -m --pidfile $PIDFILE --chuid $USER --startas $ARIA2C -- $ARGS
        log_end_msg $?
  ;;
  stop)
        log_daemon_msg "Stopping aria2c"
        start-stop-daemon --stop --retry="TERM/30/KILL/5" --exec $ARIA2C --user $USER --chuid $USER
        log_end_msg $?
  ;;
  restart|reload|force-reload)
        log_daemon_msg "Restarting aria2c"
        start-stop-daemon --stop --retry="TERM/30/KILL/5" --exec $ARIA2C --user $USER --chuid $USER
        start-stop-daemon --start --quiet -b -m --pidfile $PIDFILE --chuid $USER --startas $ARIA2C -- $ARGS
        log_end_msg $?
  ;;
  status)
        status_of_proc -p $PIDFILE $ARIA2C aria2c && exit 0 || exit $?
  ;;
  *)
        log_action_msg "Usage: /etc/init.d/aria2c {start|stop|restart|reload|force-reload|status}"
        exit 2
  ;;
esac
exit 0
Добавляем в автозапуск:
chkconfig aria2c on
Пример конфига:
# Директория загрузки
dir = /mnt/torrent/complite

# Запускать как демон
daemon = true

# Докачивать при обрывах
continue = true

# Имя пользователя и пароль для Web-Gui
rpc-user = admin
rpc-passwd = admin
Распаковываем скачаный web-гуй куда нибудь в /var/www, зайдем web-интерфейс и по пути Setting -> Connection Setting внесем наши данные из кофнига выше.
Во всяком случае у меня это заработало и теперь не приходится ходить на машину по ssh, городить screen с сессией для закачки терабайт исошников.

lighttpd, mod_rewrite для Yii

Оставлю это здесь, дабы не забыть. Надоело перекапывать google на эту тему. Есть несколько методов реализовать ЧПУ в контексте фреймворка Yii. Самый простой, поставить Apache и использовать его mod_rewrite с вот такими правилами:

AddDefaultCharset UTF-8
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Но Apache прожорлив, монструозен и не всегда нужен. В своих поделках я использую lighttpd.
Включим mod_rewrite, раскоментировав строчку mod_rewrite. Должно получится так:
server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
        "mod_rewrite",
) 
В конфигурации виртуального хоста делаем так:
$HTTP["host"] =~ "example.com" {
  server.document-root = "/var/www"
  url.rewrite-if-not-file  = (
    ".*\?(.*)" => "index.php?$1",
    "." => "index.php"
  )
}
Или так (нужно установить и включить lighttpd-mod-magnet и lua):
$HTTP["host"] =~ "example.com" {
  server.document-root = "/var/www"
  magnet.attract-physical-path-to = ( "/etc/lighttpd/rewrite.lua" )
}
Собственно сам rewrite.lua:
function file_exists(path)
  local attr = lighty.stat(path)
  if (attr) then
      return true
  else
      return false
  end
end
if (lighty.env["request.uri"] == "/" or not file_exists(lighty.env["physical.path"])) then
        lighty.env["physical.rel-path"] = "/index.php"
        lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
end
А если не охота конфигурировать каждый хост, то включаем simple-vhost и делаем примерно так:
$HTTP["host"] !~ "^(example\.com)$" {
  simple-vhost.server-root = "/var/www"
  simple-vhost.default-host = "example.com"
  simple-vhost.document-root = "public_html"
  url.rewrite-if-not-file  = (
    ".*\?(.*)" => "index.php?$1",
    "." => "index.php"
  )
}