Posted by Dan Sosedoff
on March 12, 2009
Need to identify web crawlers and mobile devices with your web-app ? Here is the list of couple regular expressions you can use (most common values):
Mobile Devices:
/(blackberry|motorokr|motorola|sony|windows ce|240x320|176x220|palm|mobile|iphone|ipod|symbian|nokia|samsung|midp)/i
Web Spyders:
/(google|yahoo|baidu|bot|webalta|archiver|crawler|spyder)/i
Posted by Dan Sosedoff
on March 09, 2009
Since i got trouble while connecting to wireless network with given parameters in linux, i tried a lot of ways to get my internet working.
So, the problem is: Windows Network manager have special option – Key index. The index is transmitted with the encrypted message. The receiver then looks-up the key corresponding to the transmitted index and uses it to decrypt the message. But linux (ubuntu) network managers i`ve tried have no key index field, so there is no way to set it up properly with gui. Connection won`t work if index value set to incorrect value.
After giving up to find any useful gui program i wrote small shell script only for one network (because i have no access to router and no chance to improve some security settings):
#!/bin/bash
# settings
interface="ath0" # wireless interface, default to wlan0
essid="NETWORK_NAME_HERE"
key="YOUR_KEY_HERE"
index="4" # can be [1..4]
# check permission
if [ "$(id -u)" != "0" ]; then
echo "Run this script under root" 1>&2
exit 1
fi
# show information
echo "Settings:"
echo "-> Interface: $interface"
echo "-> Wifi ESSID: $essid"
echo "-> Key: $key"
echo "-> Key Index: $index"
# perform association
ifconfig $interface down
iwconfig $interface essid $essid
iwconfig $interface key $key [$index]
iwconfig $interface key [$index]
ifconfig $interface up
dhclient $interface
Download shell script – http://files.sosedoff.com/9591756c/
Posted by Dan Sosedoff
on March 09, 2009
For example, in your bash shell script you`re going to use some root-specific commands like network operations, mounting devices and so on. There are couple easy ways to check if your script is executing under root privileges.
#!/bin/bash
# ...
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# ...
Another way: use EUID. When user account created a user ID is assigned to each user. Bash shell stores the user ID in $UID variable. Your effective user ID is stored in $EUID variable.
#!/bin/bash
# ...
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# ...
Posted by Dan Sosedoff
on February 15, 2009
As previous post was about fetching covers media from Amazon Web Services, this post will be about fetching covers from popular music site – Last.fm. API documentation page
#!/usr/bin/ruby
require 'rubygems'
require 'net/http'
require 'cgi'
require 'xmlsimple'
# key from API documentation
$lastfm_key = "b25b959554ed76058ac220b7b2e0a026"
$lastfm_host = "ws.audioscrobbler.com"
def fetch_cover(artist, album)
artist = CGI.escape(artist)
album = CGI.escape(album)
path = "/2.0/?method=album.getinfo&api_key=#{$lastfm_key}&artist=#{artist}&album=#{album}"
data = Net::HTTP.get($lastfm_host, path)
xml = XmlSimple.xml_in(data)
if xml['status'] == 'ok' then
album = xml['album'][0]
cover = {
:small => album['image'][1]['content'],
:medium => album['image'][2]['content'],
:big => album['image'][3]['content']
}
return cover
end
return nil
end
puts fetch_cover('Nickelback', 'Dark Horse').inspect
Download ruby script
Posted by Dan Sosedoff
on February 15, 2009
On my small project i was looking for web service to get media covers from. I found that i can use Amazon Web Services API. The documentation for this ECommerce Service is pretty old, but it still works.
More detailed information about API you can find here
#!/usr/bin/ruby
require 'rubygems'
require 'net/http'
require 'cgi'
require 'xmlsimple'
$amazon_key = "12DR2PGAQT303YTEWP02" # NOT MY KEY (FOUND ON INTERNET)
$amazon_host = "webservices.amazon.com"
def fetch_cover(artist, album)
artist = CGI.escape(artist)
album = CGI.escape(album)
path = "/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=#{$amazon_key}&Operation=ItemSearch&SearchIndex=Music&Artist=#{artist}&ResponseGroup=Images&Keywords=#{album}"
data = Net::HTTP.get($amazon_host, path)
xml = XmlSimple.xml_in(data)
if xml['Items'][0]['TotalResults'].to_s.to_i then
cover = {
:small => xml['Items'][0]['Item'][0]['SmallImage'][0]['URL'],
:medium => xml['Items'][0]['Item'][0]['MediumImage'][0]['URL'],
:big => xml['Items'][0]['Item'][0]['LargeImage'][0]['URL']
}
return cover
end
return nil
end
So, after execution of this function you will get array with 3 different images (small, medium, big).
I use XML-Simple gem for ruby. Can be installed this way
sudo gem install xml-simple
That`s it. Download script
Posted by Dan Sosedoff
on February 13, 2009
Since i started writing simple manuals about how to make system daemons i found bunch of interesting documents. For today, i just want to publish one of them instead of writing source code. This is manual originally written by Devin Watson, can be very useful for those how have no idea how to develop such system daemons. It`s only a basic information.
http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html
Posted by Dan Sosedoff
on February 06, 2009
Sometimes it`s necessary to delete all .svn directories that were created by subversion version control system. This shell command will work on all unix systems:
rm -rf `find . -name .svn`
That`s it!
Posted by Dan Sosedoff
on February 05, 2009
This is a simple piece of code which describing how to update special order field in table. For example, you have table ‘photos’:
+ --------------------------------- +
| ID | UserID | OrderID | ImgURL |
+ --------------------------------- +
| 1132 | 1 | 0 | ... |
| 2124 | 1 | 0 | ... |
| 3456 | 1 | 0 | ... |
.....................................
| N | 1 | 0 | ... |
+ --------------------------------- +
OrderID field value by default is 0. If some images has been deleted order lose its consistency.
To repair order we can use single transaction:
BEGIN;
SET @ORDER := 0;
UPDATE photos
SET order_id = (SELECT @ORDER := @ORDER + 1)
WHERE user_id = 1;
COMMIT;
After executing this on table ‘images’ we`ll get such result:
+ --------------------------------- +
| ID | UserID | OrderID | ImgURL |
+ --------------------------------- +
| 1132 | 1 | 1 | ... |
| 2124 | 1 | 2 | ... |
| 3456 | 1 | 3 | ... |
.....................................
| N | 1 | M | ... |
+ --------------------------------- +
Some developers instead of using resources of mysql script language trying to solve this problem by executing numerous call, such ‘UPDATE table SET order_id = [value] WHERE id = [id] LIMIT 1;’. It`s wrong. MySQL language have a lot of ways to make it easy. At least UDF`s.
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.
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/