HDD click problem in Ubuntu

Posted by Dan Sosedoff on January 30, 2009

Since i completely switched to ubuntu 8.04 on my laptop i got very weird “click” sounds from hard drive. I thought it was just a simple “sleep” mode, parking heads or something pretty simple. But that sound began to appear so often (sometimes 2 clicks in 1 secons)  that i cant even get sleep with that disturbing sound.. But that sound appeared only in ubuntu and never heard it in other os. Wtf  is going on? After googling for a short time i figured out what was the problem – Advanced Power Management in Ubuntu.

Solution was very simple. Just turn off this power management:

sudo hdparm -B255 /dev/sda

If you have more than one drive – the same operation but with different device. That`s it.

Writing very simple daemon in Ruby 1

Posted by Dan Sosedoff on January 24, 2009

Ruby is very powerful language, not only for web development as many can think for the first time. It is also providing all necessary resources to build system utilities and daemons. So, this post exactly about it.
Long time ago i was looking for some tool to write simple daemon in a short term. I didn`t choose C just because i was able to develop program only on special computer (i mean “production-like” environment) and the problem wasnt critical to resources. In other words – this daemon was working only few days to complete the task. Ok, lets see what we`ve got:

#!/usr/bin/ruby
# ---------------------------------------------------------------------
# MODULES
# ---------------------------------------------------------------------
require 'daemonize'
include Daemonize
include Process
# ---------------------------------------------------------------------
# CONFIGURATION
# ---------------------------------------------------------------------
$daemon = {
  :name => "Test Daemon",                  # daemon name
  :abbr => "testd",                        # daemon abbreviation
  :author => "(c) 2008 author",            # daemon author
  :version => "0.1",                       # actual version
  :file_log => "/var/log/testdaemon.log",  # log path
  :file_pid => "/var/run/testdaemon.pid",  # process id path
  :delay_sleep => 1,                       # seconds
  :user => 'tux',                          # working data user
  :grp => 'tux',                           # working data group
  :background => false,                    # background mode
  :work => true                            # daemon work flag
}
 
$daemon_log = nil
$daemon_pid = nil
 
# ---------------------------------------------------------------------
 
def daemon_log(str)
  puts "[#{Time.now.strftime("%m/%d/%Y-%H:%M:%S")}] #{str}"
end
 
def daemon_terminate
  $daemon[:work] = false
end
 
def daemon_stop
  daemon_log("Stopping working process...")
  $daemon_pid.close
  File.delete($daemon[:file_pid])
end
 
def daemon_start
  if File.exist?($daemon[:file_pid]) then
    daemon_log("Process already running. If it`s not - remove the pid file")
    exit
  end
 
  daemon_log("Starting process...")
  daemonize if $daemon[:background]
 
  begin
    $daemon_pid = File.new($daemon[:file_pid],"w")
  rescue Errno::EACCES
    daemon_log("Cannot create PID file. Check the permissions and try again!")
    $daemon_pid = nil
    exit
  end  
 
  daemon_work
end
 
def daemon_work
  if ($daemon_pid) then
    $daemon_pid.sync = true
    $daemon_pid.puts(Process.pid.to_s)
 
    begin
      while $daemon[:work] do
        daemon_log("Daemon working")
        daemon_handle_signals
        sleep($daemon[:delay_sleep])
      end
    rescue Exception => e
      daemon_log("Error: #{e.message}")
    end
 
    daemon_stop
  end
end
 
def daemon_handle_signals
  # termination signal
  Signal.trap("TERM") do
    daemon_log("TERM signal received.")
    daemon_terminate
  end  
 
  # kill signal
  Signal.trap("KILL") do
    daemon_log("KILL signal received.")
    daemon_terminate
  end
 
  # keyboard interruption
  Signal.trap("INT") do
    daemon_log("SIGINT signal received.")
    daemon_terminate
  end
 
  Signal.trap("TSTP") do
    daemon_log("SIGTSTP signal received.")
  end
end
 
def daemon_show_version
  puts "#{$daemon[:name]} v#{$daemon[:version]} #{$daemon[:author]}"
end
 
def daemon_show_usage
  daemon_show_version
  puts "Usage:"
  puts "    -b, --background        work in background mode"
  puts "    -v, --version           view version of daemon"
  puts "    -h, --help              view this help"
end
 
def daemon_parse_opts
  return true if ARGV.length == 0
 
  case ARGV[0]
    when '-b', '--background'
      $daemon[:background] = true;
      return true
 
    when '-v', '--version'
      daemon_show_version
 
    when '-h', '--help'
      daemon_show_usage
    else
      puts "Invalid argument: #{ARGV[0]}" if !ARGV[0].nil?
      daemon_show_usage
  end
 
  return false
end
 
def daemon_main
  daemon_start if daemon_parse_opts
end
 
daemon_main

This is just a basic structure of daemon, it supports background mode. I removed all unimportant information and left only main program cycles. As you can see, the entry point of whole program – daemon_main procedure. It parsing the command line parameters. In this example there is no required parameters, so daemon will run in basic mode (not background). To enable background you should specify the -d (or –background) option. Also, very important – this example needs to be executed under root or other user that have access to /var/run. Other way, PID file path can be changed to whatever you want (file_pid key). All daemon configuration variables stored in array $daemon. Also, it supports system signals handling, like SIGTERM or SIGKILL (all ruby signal constants u can explore here).

I think that`s it. Not a lot, but very simple. Download script: http://files.sosedoff.com/b57415aa/

SVN auto add and delete

Posted by Dan Sosedoff on January 16, 2009

Bored of manually delete and add files to project? Ok, me too :) So, i decided to make a simple command to work with command “svn commit”. All-in-one solution is:

#!/bin/bash
 
echo "processing files to add..."
svn status | grep “^?” | sed -r ’s/^\?[ ]+//| xargs -r svn add
 
echo "processing files to delete..."
svn status | grep “^!| sed -r ’s/^\![ ]+//| xargs -r svn delete
 
echo "processing commit..."
svn commit

Download bash script – http://files.sosedoff.com/62c99246/

Simple MySQL backup script

Posted by Dan Sosedoff on January 15, 2009

There is a small useful ruby script to backup your MySQL databases in small projects, where speed of backup not so important.
Source:

#!/usr/bin/ruby
# MySQL Backup Utility
# Usage: ./mysql_backup.rb or ruby mysql_backup.rb
 
$backup_archive = true # gzip files after processing
$backup_dir = "/home/storage/backup/" # output directory
$backup_template = "project-%s-%s.sql" # text-%dbname-%timestamp.sql
$backup_cmd = "mysqldump -u local_backup --add-drop-table --databases %s > %s"
$backup_dblist = [ # list of databases to backup
  'main',
  'users',
  'admin',
  'cards'
] 
 
def backup_database(database)
  time = Time.now()
  time_str = sprintf("%02i-%02i-%04i-%02i%02i%02i",time.day, time.month, time.year, time.hour, time.min, time.sec)
  filename = sprintf($backup_template,database,time_str)
  filename = "#{$backup_dir}#{filename}"
 
  cmd = sprintf($backup_cmd,database,filename)
  if system(cmd) then
    system("gzip --best #{filename}") if $backup_archive
  end
end
 
$backup_dblist.each do |db|
  puts "Processing database... #{db}"
  backup_database(db)
end

Paste: http://pastie.org/341839

Making URL controller easy 3

Posted by Dan Sosedoff on January 15, 2009

For example, instead of using “dirty” url`s in your web application (like test.php?param=1&val=342&fuck=bla) you can use very nice links (/this/is/nice/link/). And also, redirect all the requests to single file.

nginx configuration:

location / {
    root /var/site/public_html;
    index index.php index.html index.htm;
    if (!-e $request_filename) {
        rewrite ^/(.*)/$ /index.php?path=$request_uri last;
    }
}

The same for Apache 2:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ index.php?path=%{REQUEST_URI} [NCL]

Rewrite subdomains with nginx 0.6.x

Posted by Dan Sosedoff on January 15, 2009

Problem: You have a domain name ‘www.domain.com’ that needs to be redirected to ‘domain.com’.

Solution:

In your nginx config file (i`m keeping all configs for all sites separate in different files), befor ’server’ block configuration you should put this piese of code:

server {
    server_name www.domain.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}
server {
... actual server configuration ...
}

Configuring WebDAV Server

Posted by Dan Sosedoff on January 15, 2009

Some time ago i had reason to make couple servers being accessible by WebDAV protocol.
But all our special storage servers were running nginx 0.6.x, that also supports this protocol.
By the way, it doesn`t support meta commands such as PROPFIND, OPTIONS, so if you try to connect to server with some command-line or GUI client it will close connection due to accepting “unknown” commands, but will work only with PUT, DELETE, COPY, MOVE, MKCOL requests.
It was a huge problem, because for a long time i couldn`t figure out what the reason of reject. Server allways respond with ‘405 Not allowed’. But when i tried put file – it worked.
Also, alternate fast server Lighttpd supports all meta commands.

Simple nginx configuration:

server {
    listen 80;
    server_name localhost;
    access_log log/access.log;
    error_log log/error.log;
    charset utf-8;
    client_body_temp_path client_body_temp;
    autoindex on;
 
     location / {
          root /home/dav/public;
          dav_methods PUT DELETE MKCOL COPY MOVE;
          dav_access user:rw group:rw all:r;
          create_full_put_path on;
 
          # auth access
          auth_basic "Restricted";
          auth_basic_user_file ;
     }
}

After configuring server, you`ll need to create htpassword file, that will keep user credentials.
Simple example:

htpasswd -c /where/to/save/the/file username

More information about how to configure nginx can be found at http://wiki.codemongers.com/NginxModules

Streaming FLV videos problem in nginx 0.6.32

Posted by Dan Sosedoff on January 15, 2009

nginx, fast small webserver, supports flash flv files streaming.
I am currently using JW Player 4.0 on projects, its free, lightweight and have a lot useful features.
But, i got some problems with its latest versions. It always adding some special information, like player container resolution like this:

myvideo.flv?start=2659763&width=280&version=4.0&...

Result: cannot seek on the video.
Found a solution on ruby forum. http://www.ruby-forum.com/attachment/2307/patch.flv
You need only apply this patch to sources and rebuild nginx. That`s it.

P.S. Don`t know about older versions of nginx, but 0.6.32 from sources doesnt work with JW Player 4.0.

UFO Crashed Here

Posted by Dan Sosedoff on January 15, 2009

Ufo`s servers crashed during the flight and their craft landed here.. Ok, let`s find something to eat on this small planet ;)