Vladimir Melnik

Just another WordPress site

Some sassy fella

Did you foresaw your future life when you were younger?

At some point you may start to realize that you had foreseen all your furure life and all future events in the world around you quite a long time ago. Were there some dreams or some unexpected thoughts, even some past things that you could now consider as pretty obvious signs – all these things were quite obvious, so you somehow knew that your life will go this way or that one.

]Are you familiar with that feeling? If yes – what do you think, doesn’t that mean that you’ve made the world around you by your imagination?

Living my music

I really love music! I love to listen music, to feel it, to compose my tunes and to play them. I’m pretty sure that principles of musical harmonies, chords and progressions can be applied to varions things in the universe, because the world itself seem to be organized by the same rules. Surely, I’m not an expert in physics and mathematics, but you don’t need to be a PhD to see the obvious. :)

I decided to try an odd experiment. I’ve divided the week to 12 equal chunks complied to 12 halftones, so one week is treated as a full octave. It could look like that:


Then I’m going to “play” various chords progressions, just by doing certain things at certain hours corresponding to certain tones. For example, “playing” a C-chord means doing some things in the following periods:

  • from 00:00 till 14:00 of Monday,
  • from 08:00 till 22:00 of Wednesday,
  • from 02:00 till 16:00 of Friday.


On the next week I’ll “play” some other chord, for example, an Am-chord. Then goes an F-chord. And then – a G-chord. So, some progression will be “played”.

What it gives? I don’t know yet! :) I need to try and then I could tell about results.

What exactly I’ll do at these hours? I’m going to decide it. But, just kind of wondering, what would YOU do at some *magic* time periods if you knew they’re *magic*?

Thank you!

Virtualization Cluster Network in a Nutshell

To be honest, I’m not keen on drawing diagrams, but today I had to spend a couple of hours to sketch this one. It was needed to illustrate Ethernet-links between elements of customer’s physical infrastructure (we’re building a virtualization cluster for them).

As you might know, Apache CloudStack can help you to build a redundant cluster, it means that you can run your virtual instances on 2 virtualization hosts, and when one host needs to be shutdown all virtual instances migrates to another host.

A networking diagram

I hope, this chart could be helpful to people who’re going to set up a networking environment for Apache CloudStack-driven cloud. This drawing seems to be pretty self-descriptive, but feel free to ask any questions if you have some. :)

A simple todo list for your shell

This simple script lists today’s tasks every time you log in (or create a new window in your screen).

# Just add me to your .bash_profile:
# [ -x ~/.bash_today ] && . ~/.bash_today
if [ ! -d "${TODAYD}/today" ]; then
        mkdir -p "${TODAYD}/today"
TODAY=$(date +%F)
function toDay() {
        local DAY=${1};         shift;
        local CARD=${1};        shift;
        local TODO=${*}
        echo "${TODAYD}/${DAY}/${CARD}: ${TODO}"
                if [ ! -d "${TODAYD}/${DAY}" ]; then
                        mkdir -p "${TODAYD}/${DAY}"
        ) && echo "${TODO} [${TODAY}]" >> "${TODAYD}/${DAY}/${CARD}"
echo -n "Today is $(date +%A), ${TODAY}"
if [ -d "${TODAYD}/${TODAY}" ] && STUFF=$(ls "${TODAYD}/${TODAY}") && [ -n "${STUFF}" ]; then
        for CARD in ${STUFF}; do
                (cat "${TODAYD}/${TODAY}/${CARD}" >> "$TODAYD/today/${CARD}") &&
                        rm -f "${TODAYD}/${TODAY}/${CARD}"
        rmdir "${TODAYD}/${TODAY}"
if [ -d "${TODAYD}/today" ] && STUFF=$(ls -X "${TODAYD}/today/") && [ -n "${STUFF}" ]; then
        echo \ and here\'s what to do:
        for CARD in ${STUFF}; do
                echo -n "${CARD}) "
                cat "${TODAYD}/today/${CARD}"
        echo , don\'t you know what to do? =\)

Adding a new task is as easy as typing something like that:

toDay 2015-13-13 universe.999 Save the universe!

On the 13’th day of the 13’th month a new task will be added with priority 999 and on that day you may see:

Today is Saturday, 2015-13-13 and here's what to do:
flowers.001) Water the flowers [2015-04-20]
goodness.013) Do something good [2000-02-02]
universe.999) Save the universe! [2015-01-01]

Get updates from GitHub: https://gist.github.com/melnik13/200673d429c828e8a860.

Maintenance works without drama: how to inform visitors when the server has been shut down

Sometimes you need to shut some web-services down for a while to do some maintenance works. Of course, you have warned all users about the scheduled downtime period, but what if it’s just impossible to inform all potential victims, e.g. every potential visitor of some web-site that won’t be working? It’s a good idea to take care of those people (or bots) and to let them know what’s going on and when their websites is up. It’s easy to make a web-server showing some maintenance notice, but what if you need to shut the server down completely? If it’s a single server, not a cluster, what visitors will see when you shut it down? They will wait for the page to be loaded, but a message saying that the connection is timed out will be the only reward for their patience. It would be much better to let them know that you’re apologizing for inconveniences, working hard to fix the issue and have some prognosis on when it’ll be okay.

So, let’s involve some spare web-server (supposedly, you have some, don’t you?) and make it showing some calming message for users and visitors of their web-sites. It’s quite easy when you have a spare web-server connected to the same network or vlan, there are just few simple steps that needed to be performed.

Step 1: creating the announcement page

Maybe one of your colleagues has already wrote an announcement and published it where your users can read it, didn’t they? If yes – let’s take the text for the notice from there, if not – let’s write the message by ourselves. Of course, as we need it to be formatted properly, we should add some HTML-tags.

<!doctype html>
<title>Site Maintenance</title>
  body { text-align: center; padding: 150px; }
  h1 { font-size: 50px; }
  body { font: 20px Helvetica, sans-serif; color: #333; }
  article { display: block; text-align: left; width: 650px; margin: 0 auto; }
  a{ color: #dc8100; text-decoration: none; }
  a:hover { color: #333; text-decoration: none; }

    <h1>We&rsquo;ll be back soon!</h1>
        <p>Sorry for the inconvenience but we&rsquo;re performing some planned maintenance at the moment. If you need to you can always contact our support team by sending a message to <a href="mailto:support@tuchacloud.com"></a> or dialing +380445835583.</p>
        <p>Works can take some time, but we'll bring this website up before 4:20 of April 20th, 2015 (GMT)!</p>
        <p>&mdash; The Team of <a href="https://tuchacloud.com/">TuchaCloud</a></p>

Lots of thanks to Pitch for the sample!)

Let’s put this page somewhere, for example to /var/www/vhosts/

Step 2: configuring nginx

No, I won’t believe you don’t know how to install nginx on your operating system. So let’s suppose you’ve done it already and we only need to add the following server stanza to its configuration:

server {
  listen default_server;

  access_log /var/log/nginx/;
  error_log  /var/log/nginx/;

  location ~ .* {
    return 503;

  error_page 503 /maintenance.html;

  location = /maintenance.html {
    charset utf-8; # in case you'd like to use it
    root /var/www/vhosts/;

Step 3: interception

If the spare server is in the same IP-network with our, it’s easy to make it receive all requests intended for, just add an according alias to the network interface, for example:

ifconfig eth0:0

Well, that’s all! Just don’t forget to update the information on the maintenance page when you realize you won’t bring the service up in time you’ve promised! :)

How to check some host by arping without looking up the corresponding network interface?

Sometimes you have to check if some host replies on ARP “who-has” requests instead of simply pinging it. You probably need it when the host has its firewall configured to deny ICMP “echo” request (as you have probably noticed, most of hosts running Microsoft Windows Server are configured to ignore these requests) to check if the host is up. So, arping really helps, but to use it you have to look up the network interface on which you shall call for this host.

This simple script does it for you: it looks up for the corresponding network interface and calls the arping utility.


if [ -z "${1}" ]; then
        echo "Chocho?" >&2
        exit 1

HOSTIP="${@: -1}"

ROUTE=$(ip route get "${HOSTIP}")
        if [ -z "${ROUTE}" ]; then
        echo "Can't find the route to this host" >&2
        exit 1

IFACE=$(echo "${ROUTE}" | sed -rn "s/^.*dev (eth.[0-9\.]+)[[:space:]]+.*$/\1/gp")
        if [ -z "${IFACE}" ]; then
        echo "Can't find the interface of this host" >&2
        exit 1

exec arping -I "${IFACE}" ${@} 

Just run it with any parameters you’d like to pass to arping, it will add the “-I” parameter and execute arping.

If I ever update this script, you can get the fresh version from GitHub: https://gist.github.com/melnik13/fb2a05d4084a6c039ccb.

P.S. I’d also suggest you to use arping by Thomas Habets – it doesn’t require you to indicate the interface, as it determines it by itself.

How to restart some service when server’s load average goes high as fuck

This post’s name and script’s comments are pretty descriptive, right? :)

# Just put it to your crontab:
# * * * * * root /root/bin/lalala.sh --la1 50 --la5 20 --laf 10 --service httpd --kill --process httpd
# It will kill all httpd processes and restart httpd service when LA1 becomes greater or equal to 50, LA5 - to 20 and LA15 - to 10

OPTS=$(getopt -n $(basename ${0}) -o 1:5:f:s:kp: -l la1:,la5:,laf:,service:,kill,process: -- "${@}")
if [ "${?}" -ne 0 ]; then
        echo "Can't get options" >&2
        exit 1
eval set -- "${OPTS}"
while :; do
        case "${1}" in
                        THR1="${2}"; shift 2;;
                        THR5="${2}"; shift 2;;
                        THR15="${2}"; shift 2;;
                        SERVICE="${2}"; shift 2;;
                        KILL="1"; shift 1;;
                        PROCESS="${2}"; shift 2;;
                        shift; break;;
                        echo "Can't recognize the option: ${1}"; exit 1;;
if [ -z "${SERVICE}" ]; then
        echo "Can't understand what service shall I restart" >&2
        exit 1
if [ "${KILL}" ] && [ -z "${PROCESS}" ]; then
        echo "Can't understand what process shall I kill" >&2
        exit 1

LA=$(  uptime | sed -r 's/^.*load average: ([0-9]+)(\.[0-9]+)?, ([0-9]+)(\.[0-9]+)?, ([0-9]+)(\.[0-9]+)?$/\1\t\3\t\5/g' )
LA1=$( echo "${LA}" | cut -f1)
LA5=$( echo "${LA}" | cut -f2)
LA15=$(echo "${LA}" | cut -f3)

        [ -n "${THR1}"  ] && [ -n "${LA1}"  ] && [ "${LA1}"  -ge "${THR1}"  ] &&
        [ -n "${THR5}"  ] && [ -n "${LA5}"  ] && [ "${LA5}"  -ge "${THR5}"  ] &&
        [ -n "${THR15}" ] && [ -n "${LA15}" ] && [ "${LA15}" -ge "${THR15}" ];
        if [ "${KILL}" ]; then
                while PIDS=$(pidof ${PROCESS}); do
                        echo "Slaying ${PIDS}..."
                        kill -9 ${PIDS}
                        sleep 1
                sleep 10
                service "${SERVICE}" restart

Of course, you can get all further updates of this script from GitHub: https://gist.github.com/melnik13/04225e4e60a8d66f9ab6.

Now you can sleep tight in the night! :)

How to run commands on different servers with different login credentials

Wouldn’t it be lovely if you could run some command on a bunch of servers?

Of course, you can! Most of us would do something like that:

for HOST in host1 host2 host3; do { ssh "${HOST}" "echo ZALOOPA > /var/tmp/zaloopa"; } done

But what if there are dozens of servers with different usernames to log-in with, different SSH-keys to use and even different ports to connect to? It would be quite convenient to use some conficuration file with all these login-details:

# The format is following:
#     hostname:username:port:ssh-key #comments #tags
# All parameters besides of the first are optional
# Regular servers
# The servers where we shall use an alternative username to log in
# Servers where we shall use an alternative port to log in
# Servers where we shall use an alternative SSH-key to log in
# Servers we need to be found by some hashtags (so we can run the script with the -g parameter: "-g '#huerga'")
host10                                  #huerga
host11:user                             #huerga
host12:user:30022                       #huerga #zaebis #pizdets
host13:user:30022:~/.ssh/id_rsa.zaloppa #huerga #pizdets

No problem! Grab this simple script to have it possible:

OPTS=$(getopt -n $(basename ${0}) -o c:g:y -l command:,grep-criterias:yes -- "${@}")
if [ "${?}" -ne 0 ]; then
        echo "Can't get options" >&2
        exit 1
eval set -- "${OPTS}"
while :; do
        case "${1}" in
                        COMMAND="${2}"; shift 2;;
                        CRITERIAS="${2}"; shift 2;;
                        SURE="Y"; shift 1;;
                        shift; break;;
                        echo "Can't recognize the option: ${1}"; exit 1;;
TARGETS=$(cat ~/etc/servers | grep -E "${CRITERIAS}" | sed -e 's/[[:space:]]*#.*$//' -e '/^$/d')
if [ -z "${COMMAND}" ]; then
        echo "The command is undefined" >&2
        exit 1
while :; do
        echo -e "Our targets are:\n${TARGETS}" >&2
        [ "${SURE}" != "Y" ] && read -p "Are you sure you want to run '${COMMAND}'? (Y/N) " SURE
        case "${SURE}" in
                        for TARGET in ${TARGETS}; do
                                HOST=$(echo "${TARGET}" | sed -r -n -e 's/^([^:]+)(:([^:]*))?(:([^:]*))?(:([^:]*))?$/\1/gp')
                                USER=$(echo "${TARGET}" | sed -r -n -e 's/^([^:]+)(:([^:]*))?(:([^:]*))?(:([^:]*))?$/\3/gp')
                                PORT=$(echo "${TARGET}" | sed -r -n -e 's/^([^:]+)(:([^:]*))?(:([^:]*))?(:([^:]*))?$/\5/gp')
                                SKEY=$(echo "${TARGET}" | sed -r -n -e 's/^([^:]+)(:([^:]*))?(:([^:]*))?(:([^:]*))?$/\7/gp')
                                [ -z "${USER}" ] && USER=$(whoami)
                                [ -z "${PORT}" ] && PORT=22
                                [ -z "${SKEY}" ] && SKEY=~/.ssh/id_rsa
                                echo "Running '${COMMAND}' on ${HOST}:${PORT}..." >&2
                                ssh -i "${SKEY}" -p "${PORT}" -l "${USER}" "${HOST}" "${COMMAND}"
                        echo "So, Y or N?" >&2

Now you can do something like that:

spread.sh --command "yum -y upgrade && reboot" --grep-criteria '(#centos|#pizdos)' --yes

If I ever update this script with some new features, you could always get the latest verion from GitHub: https://gist.github.com/melnik13/be1160a5bf73e246cd5f.

Enjoy your great power, but don’t forget about great responsibility comes with it! :)

How to monitor which files are growing faster than other ones?

If you ever needed a tool to get to know which files are growing faster than other ones, you probably will be quite satisfied with this simple bash-script.

# Checking the spool directory
if [ ! -e "${SPOOL}" ]; then
        mkdir -p "${SPOOL}"
if [ ! -d "${SPOOL}" ]; then
        echo "There are no ${SPOOL} directory" >&2
        exit 1
if [ -z "${1}" ]; then
FILES=$(find "${DIR}" -type f)
TIME=$(date +%s)
if [ -z "${TIME}" ]; then
        echo "Can't determine current time" >&2
        exit 1
for FILE in ${FILES}; do
        SIZE=$(ls -nl ${FILE} | awk '{ print $5 }')
        if [ -z "${SIZE}" ]; then
                echo "Can't determine size of the ${FILE} file" >&2
        sqlite3 "${SPOOL}/db" "INSERT INTO sizes VALUES ('${FILE}', '${TIME}', '${SIZE}');"
        if [ ${?} -ne 0 ]; then
for PERIOD in 60 300 600 1800 3600 86400; do
        TIME_WAS=$((${TIME} - ${PERIOD}))
                echo "*** Since $(date --date="@${TIME_WAS}") (${PERIOD} seconds ago) ***"
                sqlite3 \
                        "${SPOOL}/db" \
                        "SELECT MAX(size) - MIN(size) AS mm, name
                                FROM sizes
                                WHERE time >= '${TIME_WAS}'
                                GROUP BY name
                                ORDER BY mm
        ) > "${SPOOL}/report_${PERIOD}"

Simply put it to your crontab:

* * * * * root /root/bin/diskhogs.sh /directory/to/monitor

Resulting reports will be put to /var/spool/diskhogs/report_*. You also can generate any reports by yourself, just use sqlite:

sqlite3 /var/spool/diskhogs/db "
    SELECT MAX(size) - MIN(size) as mm, name
        FROM sizes
            time >= '$(date --date='10 days ago' +%s)' AND
            name like '/var/lib/libvirt/images/%'
        GROUP BY name
        ORDER BY mm DESC

This query will generate the report for all files in the /var/lib/libvirt/images directory for the last 10 days.

If there are any updates, you could get them from GitHub: https://gist.github.com/melnik13/7ad33c57aa33742b9854.

Happy monitoring! :)