Change timezone on Ubuntu server (CLI only)

It should be simple to do this and it is. The hardest part was finding the correct way to do it, so for future reference:

Using the command line, you can use dpkg-reconfigure tzdata.

sudo dpkg-reconfigure tzdata

Follow the instructions to reconfigure the timezone. This was taken from the ubuntu wiki article

Cheers, Mark

Convert Mac Line endings to Linux

I was cleaning up some source code yesterday and wanted to print it all out, however the Mac line endings (we use Mac's and Ubuntu mostly) were messing up the printout on my Ubuntu machine.

A quick google later and I found the solution, a program called 'tr', posting here for next time:

tr "\r" "\n" < filewithmaclineendings.txt > filewithunixlineendings.txt

Obviously you could convert from Unix to Mac by reversing it.

tr "\n" "\r" < filewithunixlineendings.txt > filewithmaclineendings.txt

Cheers, Mark

Managing long running requests on ColdFusion

The Problem

We've been working on an application which needed significant integration with an external system which is done via web services.

During out load testing we came across a major issue with the web services when the application was under load which caused the ColdFusion application server to crash very badly.

The problem was caused by the fact that the web service calls typically took about 1 second to complete whereas pages that didn't need to use a web-service completed in about 100ms.

When we put the application under load if the number of requests that needed web-services ran at a sustained high rate then very soon all the running requests would be doing web service calls. This meant that all 25 java threads were getting swallowed up the "long running" web-service calls.

This caused all the other threads to queue up and very shortly the application fell over in a heap.

The Solution

Initially we looked a using cflock tags to handle it but this would essentially serialize all web service requests and only one web-service thread would run at any one time. This meant that the application would not be able to handle the required load.

After a bit of a brainstorming session we came up with the idea to develop a semaphore type object which would limit the amount of threads that could get tied up with long running web-service requests.

Ideally it works like this:

  • A web-service request comes in
  • It requests a thread from the Semphore object
  • If it gets one it runs the Web Service and then releases the thread

However, if the system is busy it works like this:

  • A web-service request comes in
  • It requests a thread from the Semphore object
  • It doesn't get a thread so doesn't run the web service and quickly returns and lets the user know the app is busy

Usage

In order to use the semaphore you need to set it up in a shared scope - typically application or server scope. We use it in our webservice wrapper CFC which is stored in the application scope.

<cfset variables.instance.Semaphore = createObject("component", "Semaphore").init("unique_name", 15,"logfilename")>

Here is a code example of how this looks in practice:

<cfset threadID = variables.instance.Semaphore.acquireThread()>
<cfif threadID GT 0>
   <cftry>
   <!--- We handle all errors in here to ensure we release the thread afterwards --->
      <cfinvoke webservice here>
   
      <cfcatch type="any">
      <!--- Log errors but continue so we release thread--->
      </cfcatch>
   </cftry>
   <!--- Make sure we release the thread - even if everything above explodes --->
   <cfset variables.instance.Semaphore.releaseThread(threadID)>
</cfif>

Note: One of the issues that we came across during the implementation of this was that when long running requests were caught by the long running request timeout the releaseThread function would not get called as the webservice code was timing out and it was getting killed before it hit the releaseThread line. To work around this we implemented an internal garbage collection mechanism to ensure that we didn't leak threads, or when we did we could recover from it.

This has allowed us to manage the number thread by limiting the number of long running requests so as the server gets busy it will now reject web service calls before it runs out of memory.

You can get the full code for the Semaphore object from our Opensource CF Library

"Show Full Columns" problem with CFMX and MySQL solved

We've been performing some load testing on a new website we've developed and our helpful sysadmin noticed lots of queries happening on the DB that looked like this:

SHOW FULL COLUMNS FROM `dbname`.`tablename`

We weren't intentionally doing these queries but they were coming from somewhere. A bit of detective work via google found a very enlightening article about this problem.

A quick read of this explained:

It turns out ColdFusion was asking Connector/J for the metadata on every field, which in turn triggered a SHOW FULL COLUMNS query for every varchar and text column returned.

It also went on to say that is had been fixed as of Connector/J 5.07.

On reading the release notes it mentions that the

Driver detects when it is running in a ColdFusion MX server (tested with version 7), and uses the configuration bundle coldFusion, which sets useDynamicCharsetInfo to false (see previous entry), and sets useLocalSessionState and autoReconnect to true.

However, from my testing it wasn't doing it as we were still seeing the problem. However, we are running the MultiServer version of ColdFusion which sits atop Jrun4.

So I added the parameter directly to the querystring:

&useDynamicCharsetInfo=false
So it now looks like:

This has stopped the problem, and given a significant performance gain. On one of the sites I was load testing it gave a 12% throughput increase and on another one which had less queries it gave a 4% increase.

Hope it helps.

Cheers, Mark

Monitoring multiple log files in a cluster

While chatting with my friendly local sysadmin the other day about monitoring multiple log files across our cluster of server he pointed me towards multitail.

With a little bit messing about I managed to get it doing exactly what I needed.

I created the following little script which connects to 4 remote servers and monitors the log files (file names and server names have been changed to protect the innocent).

#!/bin/bash
multitail -l "ssh server1 tail -f /var/log/myinteresting.log" \
-l "ssh server2 tail -f /var/log/myinteresting.log" \
-l "ssh server3 tail -f /var/log/myinteresting.log" \
-l "ssh server4 tail -f /var/log/myinteresting.log"

Now with a single command I can monitor the log files across the entire cluster.

Happy days. Cheers, Mark

CFMX "The Graphing service is not available" - solved

I've just completed setting up a new ColdFusion server on Ubuntu Server (I know it's not a supported config) and ran into the following problem when I went to the admin page:

The Graphing service is not available

A bit of googling turned up this Technote from Adobe which mentioned the same problem on RedHat Linux.

The redhat solution is also documented on Talking Tree but it doesn't cover Ubuntu.

For Ubuntu it's very simple - you need to install 3 libraries and you are good to go - one single line.

sudo apt-get install libXp6 libXt6 libXtst6

This will install a dozen or so packages - then restart ColdFusion and you have a shiny working install.

Cheers, Mark Lynch

Power saving tips for Ubuntu on laptops

One of the things that Ubuntu (gutsy 7.10) and probably most versions of linux) are currently lacking is out of the box support for power saving and hence suffers from poor battery life when unplugged.

My HP nc8430 also runs particularly hot by default - but I've spent a bit of time hunting down tips for reducing the power usage and heat produced from the laptop to get a longer battery life. I'm sure there are a lot more ways that power can be saved and I suspect that future versions of Ubuntu will catch up and produce the same level of battery life or even longer than windows.

Here is what I am using so far:

Set powerplay mode on ATI fglrx driver

aticonfig --lsp # show current and available modes
aticonfig --set-powerstate=1 #set to low power mode

If anyone has equivalent code for other video cards please let me know and I'll add it here.

Disable 'hal' from polling your cdrom

From powertop: 'hal' is the component that auto-opens a window if you plug in a CD but disables SATA power saving from kicking in.

sudo hal-disable-polling --device /dev/scd0

Disable bluetooth if you are not using it

sudo hciconfig hci0 down
sudo rmmod hci_usb

Remove the usb 1.1 kernel driver if not using it

Apparently the usb 1.1 driver does frequent polling and prevents the processor from staying in low power states for any length of time.

sudo rmmod uhci_hcd

Increase the VM dirty writeback time

From powertop: This wakes the disk up less frequenty for background VM activity.

echo 1500 |sudo tee /proc/sys/vm/dirty_writeback_centisecs

Turn off second processor

This is a very extreme measure and I haven't measured how much extra battery life it gives - but it is a bit cool to be able to turn it on and off if you have a dual core or dual CPU machine.

echo 0 | sudo tee /sys/devices/system/cpu/cpu1/online
and to turn it back on use the following:
echo 1 | sudo tee /sys/devices/system/cpu/cpu1/online

How cool is that?

Let me know if you come across any more tips. Cheers, Mark

Updated 17/Mar/07: Fixed commands based on feedback from Neil. Thanks Neil.

Adding Mime-type for Adobe AIR Packages on Ubuntu

If you've just put you Adobe AIR package on you server and you get something that looks like the picture below then you need to add a mime type so that apache can tell your browser what type of file it is.

The reason that apache doesn't already know about it is that the Adobe AIR format has only just been released.

To fix up a Ubuntu server all you need to do is add the following line to the /etc/mime.types file:

application/vnd.adobe.air-application-installer-package+zip air

Then restart apache with:

sudo /etc/init.d/apache restart

All done. I'm sure that the mime type will be included going forward so this won't be a problem.

SSH Portforward - Address already in use - Solved

We uses SSH portforward's to ensure security of many of our systems as it allows us to have VPN-like functionality with a very simple configuration. As our use of it has grown over time I've become more and more familiar with the following error from SSH:

bind: Address already in use
channel_setup_fwd_listener: cannot listen to port: 2000

This occurs when you are already using a particular port for another port forward. Eg in this case I might be trying to forward port 2000 to two different machines. However, I came across this great and simple way to prevent this.

The basic theory is to use a unique local ip address for each portforward host you wish to connect to instead of using localhost (127.0.0.1) for each.

Set up your Hosts file

Open up your hosts file: /etc/hosts and add entries like this:

#port forward local ip's
system1.fwd 127.0.0.2
system2.fwd 127.0.0.3
anothersystem.fwd 127.0.0.4

I've chosen the .fwd extension to remind me what they are for.

Set up your ssh config

Then in your .ssh/config file add the optional hostnames to the localforward:

#System1 forward to the http and mysql ports
host system1
hostname 111.111.111.111
localforward system1.fwd:80 127.0.0.1:80
localforward system1.fwd:3306 127.0.0.1:3306

host system2
hostname 111.111.111.222
localforward system2.fwd:80 127.0.0.1:80
localforward system2.fwd:3306 127.0.0.1:3306

When you connect to these systems the port forwards will now be set up.

You can access the port forwards by using system1.fwd or system2.fwd instead of localhost.

Eg: http://system1.fwd/ or http://system2.fwd/

Nice, thanks for the tip Cameron.

Setting up Asterisk with Faktortel on Ubuntu - HOWTO

Having just set up an asterisk box to connect to Faktortel I thought I'd post the settings I used as the ones on the Faktortel support website do not work quite right:

For a default asterisk install on Ubuntu do the following:

$ sudo apt-get install asterisk

You then need to edit the following files three files:

sip.conf

[general]
port = 5060 ; Port to bind to (SIP is 5060)
bindaddr = 0.0.0.0 ; Address to bind to (all addresses on machine)

; sets the codecs you can use. First disallow all defaults, then set our own ind ividually.
disallow = all
allow=gsm

; Setup a user with the phone number 1000 on our network.
[1000]
tos=reliability
type=friend
username=1000
host=dynamic
context=default
reinvite=no
canreinvite=no
secret=abc123
nat=yes
qualify=yes

iax.conf

; Setup the general options, including our default port for use with IAX
; the amount of bandwidth we have on our connection to the server (best left as low)
; jitterbuffer, this isn't enabled at the moment in the latest CVS but we don't want it
; to suddenly come on when it is enabled.

[general]
bandwidth=low
jitterbuffer=no
tos=lowdelay


; This line registers your server with the FaktorTel main server, what this means is that
; it tells us where you are on the internet so you can receive incoming calls from our network
; don't forget to replace "YOUR-USERNAME" and "YOUR-PASSWORD" with the ones supplied to you.

register => YOUR-USERNAME:YOUR-PASSWORD@iax.faktortel.com.au

; The following section sets up an IAX user called "faktortel", this is the user which will place
; the call from your server to our network. First we tell it not to use any other codec by setting
; our "Disallow" and "allow" settings. Then we set the type to "friend", then set our password and
; username for the faktortel network (don't forget to change these to the ones supplied to you).
; using the "host" command we tell the user which server to connect to, then using "auth" we tell
; it the type of password to look for, and finally using "qualify" we tell it to keep in touch
; with the server ever 3 seconds. (This is fast enough).

[faktortel]
disallow=all
allow=gsm
type=friend
username=YOUR-USERNAME
secret=YOUR-PASSWORD
host=iax.faktortel.com.au
auth=md5
context=incoming
qualify=yes

extensions.conf

; First we setup a context called "Default" this is our "Encapsulation" context. The only point of this
; context is to point to all our other groups in order. We only have one other outgoing context at the
; moment so we are just including one "faktortel-outgoing" however this will allow you to make a much
; more sturdy network later if you use it as a full PBX. This is also the context we use to place calls out of.

[default]
include => faktortel-outgoing


; FaktorTel-Outgoing is another context, this tells anyone who is trying to make a call out from the PBX
; which starts with a "0" to put that call out to the PSTN via FaktorTel. The format here is best
; described at "www.voip-info.org" under "configuration files" "extensions.conf".

[faktortel-outgoing]
exten => _0.,1,DIAL(IAX2/YOUR-USERNAME@faktortel/${EXTEN:1})
exten => _0.,2,Congestion

; Adding an extension for the number 1234 which will give you the Time.
exten => 1234,1,SayUnixTime
exten => 1234,2,Hangup


; This is our "incoming" context, when a call comes in from the faktortel network it is sent here
; because we set "context=incoming" in our IAX.CONF file under [faktortel]. This then tells it
; that ANY call that comes in should ring the SIP based phone at extension "1000" which we setup
; earlier.

[incoming]
; Add extension for you DID number
exten => YOUR_DID_NUMBER,1,Answer
exten => YOUR_DID_NUMBER,n,SayUnixTime
exten => YOUR_DID_NUMBER,n,Hangup

Hope this helps you get going with Asterisk. Cheers, Mark

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.