Friday, May 11, 2012

Deploying the application remotely using Capistrano

I encountered the following problems in deploying the application using Capistrano

1. The "set :deploy_to" setting in Capistrano's deployment script config/deploy.rb

The syntax of the setting is "set :deploy_to {dir_name}".  After remotely logging into the deployment server as a user, the Capistrano command "cap deploy:setup" creates a directory of {dir_name} under user's home directory and enables the group write access to the directory.

Initially, I wanted to set the deployment directory to be ~/{app_dir}, where "~/" is the user's home directory, and the {app_dir} directly contains the Ruby-on-Rails application files, therefore, I used "set :deploy_to ."

The "." indicates the current directory, which should the user's home directory after Capistrano remote logs in.

The result of the "cap deploy:setup" command was

* executing `deploy:setup'
* executing "mkdir -p . ./releases ./shared ./shared/system ./shared/log ./shared/pids"
servers: ["ip_addr"]
[ip_addr] executing command
command finished in 1055ms
* executing "chmod g+w . ./releases ./shared ./shared/system ./shared/log ./shared/pids"
servers: ["ip_addr"]
[ip_addr] executing command
command finished in 53ms

It created the directories "releases" and "shared" directly under ~/, which is a little messy. What is worse is, the . or ~/ has been enabled for group write "chmod g+w .". This affects the ssh authentication. If the user's home directory is group/world-accessible, sshd does not start (see sshd manual). So any subsequent ssh login by the user will fail:

02:33 PM ~ $ ssh mfmproject@{host}
Permission denied (publickey).

Solution:

The solution is easy and creates cleaner deployment directory structure. Instead of deploying directly under ~/, deploy under a subdirectory such as "~/webapp". Change the setting in deploy.rb to
set :deploy_to, "webapp"

* executing `deploy:setup'
* executing "mkdir -p webapp webapp/releases webapp/shared webapp/shared/system webapp/shared/log webapp/shared/pids"
servers: ["ip_addr"]
[ip_addr] executing command
command finished in 1055ms
* executing "chmod g+w webapp webapp/releases webapp/shared webapp/shared/system webapp/shared/log webapp/shared/pids"
servers: ["ip_addr"]
[ip_addr] executing command
command finished in 53ms


2. During the execution of "cap deploy:migrations" command, the Git repository requires ssh authentication of user accessing the repository from the deployment machine.

The "cap deploy:migrations" command executes

"git clone -q mfmproject@[ip_addr]:git/karen_app_0515.git webapp/releases/20110919185255 && cd webapp/releases/20110919185255 && git checkout -q -b deploy 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 && (echo 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 > webapp/releases/20110919185255/REVISION)"

Even though both Git repository and the web server are on the same machine, the Git repository still treats the clone request as a if it is coming from a user on a different machine, thus requires ssh authentication of the user.

If the command was issued in the terminal of the deployment machine, the passphrase to unlock the user's ssh RSA private key would be prompted, in order for the user to access the Git repo via ssh.

Since Capistrano script runs without user interactivity, a passphrase is never given when it is needed by the "cap deploy:migrations" command, therefore the error like this happens:

* executing "git clone -q mfmproject@[ip_addr]:git/karen_app_0515.git webapp/releases/20110919185255 && cd webapp/releases/20110919185255 && git checkout -q -b deploy 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 && (echo 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 > webapp/releases/20110919185255/REVISION)"
servers: ["ip_addr"]
[ip_addr] executing command
** [ip_addr :: err] Host key verification failed.
** [ip_addr :: err] fatal: The remote end hung up unexpectedly
command finished in 392ms
failed: "sh -c 'git clone -q mfmproject@[ip_addr]:git/karen_app_0515.git webapp/releases/20110919185255 && cd webapp/releases/20110919185255 && git checkout -q -b deploy 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 && (echo 94c0d6bb8db04921d1f6ae8659ba9fac8c4f3f00 > webapp/releases/20110919185255/REVISION)'" on [ip_addr]


Solution

Set up ssh agent forward option in Capistrano deploy.rb


ssh_options[:forward_agent] = true 


This uses local keys on the development machine (where Capistrano is running), instead of the keys on the deployment machine to access the Git repository.

3. In executing the "cap deploy:migrations" command, Capistrano uses the system-wide Ruby installation instead of the user-specific RVM ruby installation when running the bundle_install task. The system-wide Ruby installation requires sudo access which is disabled in deploy.rb.

The command fails, because sudo access to do bundle_install fails.

Solution

Configure Capistrano to use RVM ruby installation in deploy.rb:

# configure Capistrano to use user-installed rvm rubies instead of the system-wide rubies
# Note: this rvm setting is obtained from the output of "rvm info" command, or# "cat ~/.rvm/environments/default".set :default_environment, {
'PATH' => "/home/mfmproject/.rvm/gems/ruby-1.9.2-p290/bin:/home/mfmproject/.rvm/gems/ruby-1.9.2-p290@glob
al/bin:/home/mfmproject/.rvm/rubies/ruby-1.9.2-p290/bin:/home/mfmproject/.rvm/bin:/usr/local/sbin:/usr/local/bin
:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games", 'RUBY_VERSION' => 'ruby-1.9.2-p290',
'GEM_HOME' => '/home/mfmproject/.rvm/gems/ruby-1.9.2-p290',
'GEM_PATH' => '/home/mfmproject/.rvm/gems/ruby-1.9.2-p290:/home/mfmproject/.rvm/gems/ruby-1.9.2-p290@glob
al'
}


4. In executing "cap deploy:migrations", after bundle install, Capistrano reports "rake aborted"


* executing "cd webapp/releases/20110919223344 && rake RAILS_ENV=production db:migrate"
servers: ["ip_addr"]
[ip_addr] executing command
*** [err :: ip_addr] rake aborted!
*** [err :: ip_addr] You have already activated rake 0.9.2, but your Gemfile requires rake 0.8.7. Consider using bundle exec.
*** [err :: ip_addr]
*** [err :: ip_addr] (See full trace by running task with --trace)
*** [err :: ip_addr]

StackOverflow has a thread on this problem.

Solution

Add set :rake, 'bundle exec rake' to deploy.rb.



5. In executing "cap deploy:migrations", unable to access log file due to the symbolic link links to invalid files


* executing `deploy:migrate'
* executing "cd webapp/releases/20110920001304 && bundle exec rake RAILS_ENV=production db:migrate"
servers: ["ip_addr"]
[ip_addr] executing command
*** [err :: ip_addr] Rails Error: Unable to access log file. Please ensure that /home/mfmproject/webapp/releases/20110920001304/log/production.log exists and is chmod 0666. The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.
** [out :: ip_addr] (in /home/mfmproject/webapp/releases/20110920001304)

The symbolic link is broken for two files:

mfmproject@OB-MFM2:~$ ls -l webapp/releases/20110920001304/log
lrwxrwxrwx 1 mfmproject mfmproject 17 2011-09-19 17:12 webapp/releases/20110920001304/log -> webapp/shared/log

mfmproject@OB-MFM2:~$ ls -l webapp/current
lrwxrwxrwx 1 mfmproject mfmproject 30 2011-09-19 17:12 webapp/current -> webapp/releases/20110920001304
mfmproject@OB-MFM2:~$

The link destination isn't valid because "webapp/" is a relative path. 


Solution

This should be fixed in deploy.rb, in the setting"set :deploy_to, webapp". Instead of relative path, provide the full path to webapp.




Note: I replaced the actual IP address of the deployment server by "ip_addr" in the logs.

Git operation between remote and local repositories


  • Add the alias (stanford) to the remote repository
12:03 PM ~/Development/rails_projects/app_0515 $ git remote add stanford ssh://[username]@[ip_addr]/~/git/app_0515.git
12:04 PM ~/Development/rails_projects/app_0515 $ git remote
stanford
12:04 PM ~/Development/rails_projects/app_0515 $ git remote -v
stanford ssh://[username]@[ip_addr]/~/git/app_0515.git (fetch)
stanford ssh://[username]@[ip_addr]/~/git/app_0515.git (push)

  • Fetch remote repository into a local copy
02:28 PM ~/Development/rails_projects/app_0515 $ git fetch stanford
remote: Counting objects: 55, done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 51 (delta 2), reused 51 (delta 2)
Unpacking objects: 100% (51/51), done.
From ssh://[ip_addr]/~/git/app_0515
* [new branch] master -> stanford/master

  • Diff between the local, and remote repository which has been fetched to a local copy
03:22 PM ~/Development/rails_projects/app_0515 $ git diff master stanford/master --stat
Gemfile | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)

  • Got an error pushing to remote repository. The error indicates git thinks the remote repository has recent pushes that are not synced into the local repository.
03:21 PM ~/Development/rails_projects/app_0515 $ git push stanford master
To ssh://[username]@[ip_addr]/~/git/app_0515.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'ssh://[username]@[ip_addr]/~/git/app_0515.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.
  • Merge the pushes/changes in the remote repository into the local repository
03:22 PM ~/Development/rails_projects/app_0515 $ git merge stanford/master
Merge made by recursive.

  • Push to the remote again, this time it succeeds.
03:22 PM ~/Development/rails_projects/app_0515 $ git diff master stanford/master --stat
Gemfile | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
03:22 PM ~/Development/rails_projects/app_0515 $ git push stanford
Counting objects: 10, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 978 bytes, done.
Total 6 (delta 3), reused 0 (delta 0)
To ssh://[username]@[ip_addr]/~/git/app_0515.git
a0226b1..2523dd3 master -> master
03:22 PM ~/Development/rails_projects/app_0515 $ git diff master stanford/master --stat
03:22 PM ~/Development/rails_projects/app_0515 $




TextMate tips and shortcut keys

  • Autocompletion: type the first few letters, "ESC" and "Shift-ESC"
  • Incremental forward/backward search: Control-S / Control-Shift-S

Getting a USB GSM modem working on Ubuntu


I have USB GSM modem working on a MAC, and have been using it to send SMS. Now I need to get the same modem working on a Ubuntu 10.04. Here are the steps I took to get it working on Ubuntu

When I first plug the modem into the USB port, the modem is detected as a CD-ROM device. A CD-ROM icon appears on the desktop. Ubuntu also detects the modem as a storage device, as I can tell, from issuing a few commands.
  • the device appears as /dev/sr# (# is number which varies), a byte stream device
  • the command "lsusb" output shows the device as "Bus 002 Device 005: ID 1c9e:f000." From what I read on the Internet, "f000" indicates it is a memory device.
  • the command "ls /dev/disk" shows there is disk "by-label" of "Modem", and "by-id" of usb-USBModem_Disk_1234567890ABCDEF-0:0.
So all evidences show the modem isn't detected as a modem. Via Google search, I found out it is the effect of the ZeroCD feature that the modem manufacturers have been putting in the modem. Here is a wiki description on it. Essentially, the USB modem has a bit flash storage which stores the driver of the modem. When the modem is plugged into a Windows or MAC machine, it first runs as a storage device which auto-installs the driver, the driver then switches the modem out of the storage mode into the modem mode. On a Ubuntu, the driver doesn't run and install, therefore the modem remains as a storage device.

To switch the USB modem out of the storage mode and into the modem mode, I found the Sakis3G script. It is simple and works very well.

$ gunzip sakis3g.zip

$ sudo cp sakis3g /usr/bin

$ cd /usr/bin

$ ls -l sakis3g



Here are the model of the modem and the version of Ubuntu that I'm using:
GSM modem: Zoom 4595 3G tri-band USB modem
Ubuntu: 10.04.3 LTS

Monday, February 13, 2012

Donald Knuth answered my question!

In American writing, when quoting something in a sentence, the punctuation comma or period which ends the sentence always goes inside the quotation marks, such as the following:


Whitman famously said "I contain multitudes."


However, I always wondered what if I'm writing a computer science paper and quoting a variable name, putting the punctuation inside the quotation marks seem strange and can appear confusing to the reader -- is the comma or period part of the variable name?

Alas, Donald Knuth answered my question in his Mathematical Writing


The normal style rules for English say that commas and periods should be placed in-side quotation marks, but other punctuation (like colons, semicolons, question marks, exclamation marks) stay outside the quotation marks unless they are part of the quotation. It is generally best to go along with this illogical convention about commas and periods, because it is so well established, except when you are using quotation marks to describe some text as a specific string of symbols. For example,

Good: Always end your program with the word "end".


So my intuition is right, in computer science writing, leave the symbols alone!

Wednesday, February 1, 2012

Comma (,) generates a newline in Ruby "puts"

ruby-1.9.2-p290 :010 > first = "ruby"
=> "ruby"
ruby-1.9.2-p290 :011 > second = "rails"
=> "rails"
ruby-1.9.2-p290 :012 > puts first + second
rubyrails
=> nil
ruby-1.9.2-p290 :013 > puts first, second
ruby
rails
=> nil

Test code inside Rails Console

11:13 AM ~/{application dir}/ $ rails console
Loading development environment (Rails 3.0.5)
ruby-1.9.2-p290 :001 > Gsm::Modem.convert_string_from_ascii_to_char("6900500068006F006E00650d0a")
=> "iPhone"

Thursday, December 22, 2011

Automatically switch the GSM modem to modem mode after reboot



# added by Karen to configure udev to automatically switch gsm modem

# run sakis3g
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1c9e", ATTR{idProduct}=="f000", RUN+="/usr/local/bin/sakis3g switchonly"





Plug in the GSM modem. The mode switch should be automatically. The udev rule mode switch operation can be monitored in /var/log/syslog.

Monday, November 21, 2011

How to comment source code in TextMate

Apple-/
Press the apple key and the forward slash, toggle comment

Alt-Apple-/
Comment a block. Also commet subset of a line

"head" tab-key
Type "head" and press tab. Insert a comment header at top of the file

Control-Shift-B
Insert a comment banner on the top of declarations, functions, etc.

"todo" tab-key
Type "todo" and press tab. Insert a todo bloack

Must enable Source and TODO in the Bundle filter list.

Friday, November 4, 2011

Cron + Whenever + Rake

Sample Rake code

namespace :test do
desc "Pick a random participant from database"
task :pick_participant => :environment do
if Rails.env.production?
# MySQL is used as the production DB, its random function is RAND()
p = Participant.find(:first, :order => 'RAND()')
else
# sqlite3 is used as the development DB, its random function is random()
p = Participant.find(:first, :order => 'random()')
end
puts "#{Time.now}"
puts "* environment is: #{Rails.env}"
puts "* picked participant: #{p.first_name}"
end
end


To test the rake task from command line

$ bundle exec rake test:pick_participant

2011-11-04 10:49:08 -0700
* environment is: development
* picked participant: Macy



Add the rake task to Whenever gem's schedule.rb

every 1.minutes do
rake "test:pick_participant"
end


Whenever defaults the environment to "production", to specify a different environment to run:


every 1.minutes do
rake "test:pick_participant RAILS_ENV=development"
#rake "test:pick_participant"
end


Call Whenever to update the crontab

$ whenever --update-crontab app_0515
[write] crontab file updated

$ crontab -l

# Begin Whenever generated tasks for: app_0515
* * * * * /bin/bash -l -c 'cd /Users/[username]/Development/rails_projects/app_0515 && RAILS_ENV=production bundle exec rake test:pick_participant --silent'

# End Whenever generated tasks for: app_0515

Monday, October 24, 2011

Steps to deploy changes to a RoR application to the production machine

List the differences between local (deployment) and the remote (production) Git repositories

$ git diff master <alias of the production remote repo>/master --stat


The steps to push changes to remote Git, and deploy the changes on the production server:

$ git add .
$ git commit -m "modified ... files"
$ git push < alias of the production remote repo >

If there are no database schema changes to deploy:
$ cap deploy

If there are database schema changes:
$ cap deploy:migrations

List of steps to set up GSM modem on Ubuntu

After rebooting or waking up from hibernation on Ubuntu, the GSM modem is detected as a storage device, as shown by the CD-Rom icon on the GNOME desktop.

Follow these steps to set up and verify that the modem is working
  • run "sakis3g switchonly" command. The result should be successful, with the output message "Modem switched to 1c9e:9603." The CD-Rom icon should disappear from the desktop.
  • do "ls /dev/ttyUSB*". Make sure the modem shows up as /dev/ttyUSB* devices (/dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2).
  • run "minicom -s -c on"
  • inside minicom
    • select "Exit" to exit the configuration menu, and start using minicom.
    • type "AT", press Enter make sure the response is OK.
    • type "AT+CMGF=1" to set to text mode, press Enter, the response should be OK
    • type "AT+CMGS="+1408xxxxxxx", press Enter , the prompt > should appear next
    • after the prompt >, type the SMS text
    • type Ctrl-Z to end the SMS text
    • should see the response "+CMGS: " followed by "OK"
If the SMS is received by the intended mobile phone, then the GSM modem is working.

Note: this assumes the minicom serial port configured in /etc/minicom/minirc.dfl

# Machine-generated file - use "minicom -s" to change parameters.
pu port                /dev/ttyUSB2

Type "Ctrl-A Z" and "X" to exit minicom.

No VBA

Microsoft Office for MAC 2006 doesn't support VBA (Visual Basic for Applications). That's a bummer.

I need to find another solution for calculating timesheet hours in Excel.

Friday, October 21, 2011

Use Meld as a GUI for Git diff

To diff a directory in the workspace with Git's staging area

06:24 PM ~/app_0515 $ git difftool -t meld app/views

Viewing: 'app/views/participants/index.html.erb'
Hit return to launch 'meld':

Viewing: 'app/views/sent_messages/index.html.erb'
Hit return to launch 'meld':

Viewing: 'app/views/sent_messages/show.html.erb'
Hit return to launch 'meld':


To diff between the master branch and a remote branch

07:37 PM ~/app_0515 $ git difftool -t meld home/master master

Viewing: 'app/controllers/participants_controller.rb'
Hit return to launch 'meld':


Viewing: 'app/helpers/application_helper.rb'
Hit return to launch 'meld':
Viewing: 'app/models/participant.rb'
Hit return to launch 'meld':

Viewing: 'app/views/participants/index.html.erb'
Hit return to launch 'meld':

Viewing: 'app/views/sent_messages/index.html.erb'
Hit return to launch 'meld':

Viewing: 'app/views/sent_messages/show.html.erb'
Hit return to launch 'meld':



To diff between the repository and the staging area:
12:42 PM ~/lib/rubygsm $ git difftool -t meld HEAD core.rb

Viewing: 'lib/rubygsm/core.rb'
Hit return to launch 'meld':




Getting a USB GSM modem working on Ubuntu (part II)

After getting the USB modem successfully detected as a modem on Ubuntu, the next step is to try it out, and use it to send some SMS.

I use the program Minicom.

First install Minicom
$ sudo apt-get install minicom

The installation is fast and straightforward.

Configure Minicom's serial port as root

$ sudo minicom -s -c on

The minicom's text box menu should appear with the following options:
Filenames and paths
File transfer protocols
Serial port setup
Modem and dialing
Screen and keyboard
Save setup as dfl
Save setup as..
Exit
Exit from Minicom

Select "Serial port setup". Under the setup,
A - Serial Device : dev/ttyUSB2
B - Lockfile location : /var/lock
C - Callin Program :
D - Callout Program :
E - Bps/Par/Bits : 115200 8N1
F - Hardware Flow Control : Yes
G - Software Flow Control : No

There are /dev/ttyUSB0, USB1, and USB2 associated with the modem. Selecting ttyUSB0 or ttyUSB1 causes Minicom to freeze at "initializing modem" stage, and only ttyUSB2 works.

Back to the top menu, select "Save setup as dfl" to save the serial port setup to the file "/etc/minicom/minirc.dfl". This step requires root access. and is the reason for running Minicom with sudo. Once serial port is configured, the subsequent run of minicom can be without sudo.

Select "Exit" to exit the configuration menu. Minicom should briefly show a text box that says "Initializing Modem". When initialization is done, the terminal shows:

Welcome to minicom 2.4

OPTIONS: I18n
Compiled on Jan 25 2010, 06:49:09.
Port /dev/ttyUSB2

Press CTRL-A Z for help on special keys

AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0
OK


to send an SMS using AT commands inside Minicom
Type the following AT commands:

  • type "AT+CMGF=1", press , the response should be OK
  • type "AT+CMGS="+1408xxxxxxx", press , the prompt > should appear next
  • after the prompt >, type the SMS text
  • type Ctrl-Z to end the SMS text
  • should see the response "+CMGS: " followed by "OK"

Here is how it looks like in the Minicom terminal:

AT
OK
AT+CMGF=1
OK
AT+CMGS="+1408xxxxxxx"
> test sending SMS from Ubuntu on Oct 21, 2011

+CMGS: 24

OK


Great! Now I can send SMS using the GSM modem on Ubuntu!

Getting a USB GSM modem working on Ubuntu (part I)

I have the USB GSM modem working on a MAC, and have been using it to send SMS. Now I need to get the same modem working on a Ubuntu 10.04.


When I first plug the modem into the USB port, the modem is detected as a CD-ROM device. A CD-ROM icon appears on the desktop. Ubuntu also detects the modem as a storage device, as I can tell, from issuing a few commands.
  • the device appears as /dev/sr# (# is number which varies), a byte stream device
  • the command "lsusb" output shows the device as "Bus 002 Device 005: ID 1c9e:f000." From what I read on the Internet, "f000" indicates it is a memory device.
  • the command "ls /dev/disk" shows there is disk "by-label" of "Modem", and "by-id" of usb-USBModem_Disk_1234567890ABCDEF-0:0.
So all evidences show the modem isn't detected as a modem. Via Google search, I found out it is the effect of the ZeroCD feature that the modem manufacturers have been putting in the modem. Here is a wiki description on it. Essentially, the USB modem has a bit flash storage which stores the driver of the modem. When the modem is plugged into a Windows or MAC machine, it first runs as a storage device which auto-installs the driver, the driver then switches the modem out of the storage mode into the modem mode. On a Ubuntu, the driver doesn't run and install, therefore the modem remains as a storage device.

To switch the USB modem from the storage mode and to the modem mode, I found the Sakis3G script. It is easy to run and works very well.

$ gunzip sakis3g.zip

$ sudo cp sakis3g /usr/bin

$ cd /usr/bin

$ ls -l sakis3g
-rw-r--r-- 1 root root 214619 2011-10-18 17:58 sakis3g

Change the group of sakis4g to "dialout" which has all the users who are allowed to access the modem
$ sudo chown root:dialout sakis3g

$ ls -l sakis3g
-rw-r--r-- 1 root dialout 214619 2011-10-18 17:58 sakis3g

$ sudo chmod 750 sakis3g

$ ls -l sakis3g
-rwxr-x--- 1 root dialout 214619 2011-10-18 17:58 sakis3g

I have to install a few dependencies in order to run Sakis3G
$ sudo apt-get install ppp sharutils xterm 9menu xosd-bin wget

I create a Sakis3G configuration file under /ect/sakis3g.conf, contained the following switches
--console
--sudo
--debug

These switches configures Sakis3G to run in terminal console, as root, and with detailed debug messages.

To run Sakis3G
$ sakis3g switchonly

Sakis3G spills out lots of debug messages. At the end, there should be a message like this

Modem switched to 1c9e:9603

In addition, the CD-Rom icon disappears from the desktop. Running the same set of commands again to verify the mode of the mode shows

  • the path /dev/sr1 has disappeared, and /dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2, which are character stream devices, have appear. (Note sometimes, the numbering may be USB1, USB2, and USB3)
  • the command "lsusb" shows the device as "Bus 002 Device 006: ID 1c9e:9603." The device ID has changed from 1c9e:f000 to 1c9e:9603
  • the command "ls /dev/disk/by-id" still shows the disk usb-USBModem_Disk_1234567890ABCDEF-0:0, but the path "/dev/disk/by-label" no longer exists


So voila, the USB GSM modem has been successfully switched to the modem mode!

Each time the USB modem is power-cycled due to the system reboots or wakes up from hibernation, the modem returns to the initial storage mode. So the Sakis3G script must be run again to switch the mode.


Here are the model of the modem and the version of Ubuntu that I'm using:
GSM modem: Zoom 4595 3G tri-band USB modem
Ubuntu: 10.04.3 LTS

Now that the modem is running as a modem under Ubuntu, the next step is to control it and send SMS via it. That'll be Part II.

Sunday, October 16, 2011

The file type indicator in Ubuntu "ls -l" command output

The first field of the output of "ls -l" is a string of 10 character that looks like this

drwxr-xr-x

This first character indicates file type. The common indicators are:

- : a plain file
d: a directory
l: a symbolic link
c: a character device, such as /dev/tty0
b: a block device, such as /dev/sda

Wednesday, October 12, 2011

Monday, October 3, 2011

Ruby Bundler

From Gem Versioning and Bundler: Doing it Right

Key pointers from the article
  • When running an executable, ALWAYS use bundle exec [command]. Quoting from the bundler documentation: In some cases, running executables without bundle exec may work, if the executable happens to be installed in your system and does not pull in any gems that conflict with your bundle. However, this is unreliable and is the source of considerable pain. Even if it looks like it works, it may not work in the future or on another machine.
  • When you run an executable from the command line without bundle exec, this wrapper invokes Rubygems, which then uses the normal Rubygems activation mechanism to invoke the gem’s executable. This has changed in the past several months, but Rubygems will invoke the latest version of the gem installed in your system, even if your Gemfile.lock specifies a different version. In addition, it will activate the latest (compatible) installed version of dependencies of that gem, even if a different version is specified in your Gemfile.lock.
  • The only exception to the above rules is the rails executable. As of Rails 3.0, the executable simply looks for a script/rails file, and execs that file. The generated script/rails loads the local boot environment, which invokes bundler immediately.
This explains when the Gemfile specifies Rails gem of "3.0.5", and the system Rails gem is "3.1.0", typing the command "rails -v" inside and outside the application root directory gives different version value

Inside application root directory:
06:12 PM ~/Development/rails_projects/app_0515 $ rails -v
rails Rails 3.0.5

Outside application root directory:
06:21 PM ~/Development/rails_projects $ rails -v
Rails 3.1.0

Tuesday, September 6, 2011

The first day of being on my own


  • Ubuntu command for finding out which users are logged in: who
[username]@[hostname]:~$ who
[username] tty7 2011-08-09 15:00 (:0)
[username] pts/1 2011-09-06 13:54 (c-98-234-53-135.hsd1.ca.comcast.net)


  • what do the terms "tty" and "pts" mean?

TTY Definition: Teletypewriter originally and now also means any terminal on Linux/Unix systems. It also means any serial port on Unix/Linux systems.

PTS Definition: Stands for pseudo terminal slave.

The difference between TTY and PTS is the type of connection to the computer. TTY ports are direct connections to the computer such as a keyboard/mouse or a serial connection to the device. PTS connections are SSH connections or telnet connections. All of these connections can connect to a shell which will allow you to issue commands to the computer.

http://www.question-defense.com/2009/09/11/what-do-pts-and-tty-mean-on-linux-what-is-the-difference-between-the-two-terminal-types

  • VNC into Ubuntu GNOME remote desktop
  1. make sure GNOME vino-server is running on remote host
Check that vino-server is running. Here it is process 1302.

[username]@[hostname]:~$ ps -ef | grep vino
[username] 1302 1220 0 Aug09 ? 00:22:03 /usr/lib/vino/vino-server --sm-disable
[username] 22988 22953 0 20:22 pts/0 00:00:00 grep --color=auto vino

Make sure the vino-server is listening on port 5900. Here is PID 1302 matches the port 5900 to the vino-server process .

[username]@[hostname]:~$ netstat -nlp | grep vino
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp6 0 0 :::5900 :::* LISTEN 1302/vino-server
unix 2 [ ACC ] STREAM LISTENING 8065 1302/vino-server /tmp/orbit-[username]/linc-516-0-25de38931f71d

  1. set up ssh local port forwarding to the local host
On local host, issue the command "ssh -L 5900:localhost:5900 [username]@[remote host ip address]

This forwards remote host's desktop the my local machine's port 5900.
  1. run VNC on local machine
Launch Chicken of VNC. Start a connection. Set Host to "localhost" and Display to "0" which is acutally port 5900, leave password empty, and use default for other fields. Then connect.



The remote desktop for the user account of "[username]" on the remote host should appear in the VNC window. Yah, it works!

Tomorrow, onto deploying the RoR application to the laptop's apache webserver!

A note about vino-server

Note the vino-server is the default VNC server in Ubuntu. It is part of the GNOME desktop. It doesn't start automatically from bootup, and is only started when a user has logged into the account and started the GNOME desktop. Currently, Adrian has left the user "[username]" locally logged into the Ubuntu laptop, therefore, the vino-server is running for the user "[username]".

If the laptop was a monitor-less machine where it is not possible for a user to locally log into the machine, this workaround may work:

References: