Wednesday, August 31, 2011

Setting up the VNC Server in Mac OS X 10.7 aka Lion

SkyHi @ Wednesday, August 31, 2011
A VNC server has been included with every edition of Mac OS X, including Mac OS X 10.7 – aka Lion. Let’s walk through how to start the server on Lion.
VNC is an acronym of Virtual Network Computing. You can use your Mac’s free VNC support to remotely connect and control your Mac over a network. You can even control your Mac remotely over the Internet.
In Mac OS X 10.5, aka Tiger, Apple introduced Screen Sharing to the Finder. While Screen Sharing appears to be built on VNC, it uses a more sophisticated authentication process that stops most generic VNC clients connecting.
To start a general VNC server on your Mac you need to click a few check boxes.

Starting the Mac OS X 10.7 VNC Server

  1. Launch the System Preferences.
    Open the System Preferences
    Open the System Preferences
  2. Select the Sharing preferences.
    Navigate to the Screen Sharing preferences in the System Preferences
    Navigate to the Screen Sharing preferences in the System Preferences
  3. Enable Screen Sharing within the Service list.
    Enable Screen Sharing in the Service list
    Enable Screen Sharing in the Service list
  4. Click Computer Settings… to show the VNC password setting.
    Set up your VNC server with the Computer Settings sheet
    Set up your VNC server with the Computer Settings sheet
  5. Enable VNC viewers may control screen with password:.
  6. Enter a strong password.
  7. Click OK to save your settings.
Your Mac is now running a VNC server and can be connected to from other computers using the standard VNC port (TCP/IP port 5900). Those connecting will need to use the password you entered in step 6.
The VNC server will start every time you power on your Mac. If you want to stop the VNC server, navigate to the Sharing preferences and disable Screen Sharing.


Screen Sharing with Mac OS X and Windows 7 – or possibly any other Windows

SkyHi @ Wednesday, August 31, 2011
Today, I discovered how easy it is to share my school’s Mac OS X (10.5.x) screen with another non-Mac OS computer. I know it is not a sophisticated or such but I’m posting it here as I know this might not be obvious to most Windows user or even Mac user who often live in their own world.
My first attempt to do this screen sharing thing is by following this super complex tutorial.
The tutorial by Mark Pilgrim comes with videos and links and nice background music and such – making it looks highly reliable for beginner like me. It sounds like a very secure procedure, with explanation about SSH, man-in-the-middle and many more. However, this tutorial miss one crucial aspect regarding setting up fixed domain, tcp-forwarding and those ip related stuff that might confuse 99% of world population. Not to mention his tutorial only shows configuration for home internet with a particular ISP.  The mac that I use for example was located behind CMU’s firewall and some other obstruction, making his tutorial to be only for geeks.
I could not set up the screen sharing capability through his tutorial. :(
*swearing phase*
For some reason all the VNC client that I use, RealVNC, TightVNC, UltraVNC does not seems to work properly. The clients fails with message like: ”Server did not offer supported security type” (tightVNC), ”No matching security types” (realVNC), ”Incompatible Version” (UltraVNC).
Then I google this error message only to found out this very long tutorial on how to tweak Mac to accept screen sharing. The tutorial can be found in this forum:
In short, the tutorial asks me to perform some kind of surgery to the mac machine which obviously I was not so keen of doing so.
*swearing phase*
Then Justin, one of my research mentor pointed out that for mac, there should be no additional set up other than setting up screen sharing. He suspects its a mac-windows uneasy relationship thing.
After few googling I stumble upon one of the forum post somewhere – I forgot from where but it basically said I need to set the password for screen sharing so that those windows based client can actually connect to the mac.
Here is how.
Go to (top-left-apple)-> system preferences->sharing->tick screen sharing together with the users that can be allowed to screen share.
Go to system preferences and then Sharing
Click Computer Setting to set up the password for allowing screen share.


Port forward: 5900 tcp for screen sharing over Internet

Using Screen Sharing (VNC) Over SSH on OSX

SkyHi @ Wednesday, August 31, 2011
Tunneling VNC over SSH has several benefits. For one, if you are using a non-Mac version of VNC, your traffic is probably going over the network unencrypted. By default, the Mac VNC client encrypts keystrokes, including the login.
Another benefit of using VNC over SSH is that your client Mac may be behind a firewall, which you cannot reach directly. If there is some other host, like maybe the firewall itself, which you can SSH to, then you can use SSH port forwarding to “bounce” your VNC session off of that host and connect from there to your client Mac.

This procedure assumes that the remote Mac has SSH (“Remote Login” in Sharing Preferences) enabled, and you can login with it. Suppose that you want to connect to with VNC and your user account on that machine is remoteuser. Open Terminal, and issue the command:

$ ssh -L 
Login at the prompt. Once you’ve logged in, your SSH tunnel is set up. Now simply connect to vnc://localhost:5901 (via Finder -> Go -> Connect to Server), and your VNC traffic will be automagically transported over a secure SSH tunnel to the remote host, and you should get a VNC login prompt.
Connect with VNC
VNC Login Screen
If is behind a firewall that is preventing access via SSH, but you can access another host via SSH, and that host can access via SSH, then you can forward your traffic through the accessible host. Suppose that host is called Run:

$ ssh -L 
Login to, and now when you connect to vnc://localhost:5901, your network traffic will go through an SSH tunnel to, and will be forwarded from there to Isn’t SSH wonderful?

Tuesday, August 30, 2011

php script date and grep

SkyHi @ Tuesday, August 30, 2011

$mail_to_array = array("","");
$mail_log_path = "/var/log/maillog";

echo "Producing filtered maillog..";

$generated_date_month = date("M");
$generated_date_day = date("j");

if(strlen($generated_date_day) == 1) {
    $gen_date = "$generated_date_month  $generated_date_day";
}else {
    $gen_date = "$generated_date_month $generated_date_day";

$execution_string = "grep unknown $mail_log_path | grep '$gen_date' > /tmp/.unknownhack";

$command = "mail -s '[Unknown_user_hack potato] $HOSTNAME - date()' < /tmp/.unknownhack";


FPDF – Creating PDF files using PHP

SkyHi @ Tuesday, August 30, 2011
What is FPDF?

I came across thsi little gem while searching for a PHP class that allowed me to create PDFs on the fly using PHP. Basically, FPDF is a PHP class which generates PDF files using PHP. It is a free class and full documentation of its use and hw to use it can be found here.

With FPDF you can format a PDF in the same way that you would any PDF. There is support for header and footers, page breaks, images, colors and font-styling and page compression amongst other things.

FPDF works with PHP4 and PHP5.

The class is available for download from the FPDF site.

Once downloaded, put the class into site wherever you fancy and creating a PDF can be as simple as using the following code:



$pdf = new FPDF();

$pdf->Cell(40,10,'Hello World!');



mysql last update file

SkyHi @ Tuesday, August 30, 2011
#find . -iname "*.MYD" -mtime -720

Find Files By Access, Modification Date / Time Under Linux or UNIX do not remember where I saved pdf and text files under Linux. I have downloaded files from the Internet a few months ago. How do I find my pdf or text files?
You need to use the find command. Each file has three time stamps, which record the last time that certain operations were performed on the file:

[a] access (read the file's contents) - atime
[b] change the status (modify the file or its attributes) - ctime
[c] modify (change the file's contents) - mtime
You can search for files whose time stamps are within a certain age range, or compare them to other time stamps.
You can use -mtime option. It returns list of file if the file was last accessed N*24 hours ago. For example to find file in last 2 months (60 days) you need to use -mtime +60 option.
  • -mtime +60 means you are looking for a file modified 60 days ago.
  • -mtime -60 means less than 60 days.
  • -mtime 60 If you skip + or - it means exactly 60 days.
So to find text files that were last modified 60 days ago, use
$ find /home/you -iname "*.txt" -mtime -60 -print

Display content of file on screen that were last modified 60 days ago, use
$ find /home/you -iname "*.txt" -mtime -60 -exec cat {} \; 

Count total number of files using wc command
$ find /home/you -iname "*.txt" -mtime -60 | wc -l

You can also use access time to find out pdf files. Following command will print the list of all pdf file that were accessed in last 60 days:
$ find /home/you -iname "*.pdf" -atime -60 -type -f

List all mp3s that were accessed exactly 10 days ago:
$ find /home/you -iname "*.mp3" -atime 10 -type -f

There is also an option called -daystart. It measure times from the beginning of today rather than from 24 hours ago. So, to list the all mp3s in your home directory that were accessed yesterday, type the command
$ find /home/you -iname "*.mp3" -daystart -type f -mtime 1 

  • -type f - Only search for files and not directories

-daystart option

The -daystart option is used to measure time from the beginning of the current day instead of 24 hours ago. Find out all perl (*.pl) file modified yesterday, enter:
find /nas/projects/mgmt/scripts/perl -mtime 1 -daystart -iname "*.pl"
You can also list perl files that were modified 8-10 days ago, enter:
To list all of the files in your home directory tree that were modified from two to four days ago, type:
find /nas/projects/mgmt/scripts/perl -mtime 8 -mtime -10 -daystart -iname "*.pl"

-newer option

To find files in the /nas/images directory tree that are newer than the file /tmp/foo file, enter:
find /etc -newer /tmp/foo
You can use the touch command to set date timestamp you would like to search for, and then use -newer option as follows
touch --date "2010-01-05" /tmp/foo
# Find files newer than 2010/Jan/05, in /data/images
find /data/images -newer /tmp/foo
Read the man page of find command for more information:
man find


Monday, August 29, 2011

Why you should learn just a little Awk - A Tutorial by Example

SkyHi @ Monday, August 29, 2011
In grad school, I once saw a prof I was working with grab a text file and in seconds manipulate it into little pieces so deftly it blew my mind. I immediately decided it was time for me to learn awk, which he had so clearly mastered.

To this day, 90% of the programmers I talk to have never used awk. Knowing 10% of awk's already small syntax, which you can pick up in just a few minutes, will dramatically increase your ability to quickly manipulate data in text files. Below I'll teach you the most useful stuff - not the "fundamentals", but the 5 minutes worth of practical stuff that will get you most of what I think is interesting in this little language.

Awk is a fun little programming language. It is designed for processing input strings. A (different) prof once asked my networking class to implement code that would take a spec for an RPC service and generate stubs for the client and the server. This professor made the mistake of telling us we could implement this in any language. I decided to write the generator in Awk, mostly as an excuse to learn more Awk.  Surprisingly to me, the code ended up much shorter and much simpler than it would have been in any other language I've ever used (Python, C++, Java, ...).  There is enough to learn about Awk to fill half a book, and I've read that book, but you're unlikely to be writing a full-fledged spec parser in Awk.  Instead, you just want to do things like find all of your log lines that come from ip addresses whose components sum up to 666, for kicks and grins.  Read on!

For our examples, assume we have a little file (logs.txt) that looks like the one below.  If it wraps in your browser, this is just 2 lines of logs each staring with an ip address. [28/Sep/2010:04:08:20] "GET /robots.txt HTTP/1.1" 200 0 "msnbot" [28/Sep/2010:04:20:11] "GET / HTTP/1.1" 304 -  "Baiduspider"

These are just two log records generated by Apache, slightly simplified, showing Bing and Baidu wandering around on my site yesterday.

Awk works like anything else (ie: grep) on the command line.  It reads from stdin and writes to stdout.  It's easy to pipe stuff in and out of it.  The command line syntax you care about is just the command awk followed by a string that contains your program.

awk '{print $0}'

Most Awk programs will start with a "{" and end with a "}".  Everything in between there gets run once on each line of input.  Most awk programs will print something.  The program above will print the entire line that it just read, print appends a newline for free.  $0 is the entire line.  So this program is an identity operation - it copies the input to the output without changing it.

Awk parses the line in to fields for you automatically, using any whitespace (space, tab) as a delimiter, merging consecutive delimiters.  Those fields are available to you as the variables $1, $2, $3, etc.

echo 'this is a test' | awk '{print $3}'  // prints 'a'
awk '{print $1}' logs.txt


Easy so far, and already useful.  Sometimes I need to print from the end of the string though instead.  The special variable, NF, contains the number of fields in the current line.  I can print the last field by printing the field $NF or I can just manipulate that value to identify a field based on it's position from the last.  I can also print multiple values simultaneously in the same print statement.

echo 'this is a test' | awk '{print $NF}'  // prints "test"
awk '{print $1, $(NF-2) }' logs.txt

Output: 200 304

More progress - you can see how, in moments, you could strip this log file to just the fields you are interested in.  Another cool variable is NR, which is the row number being currently processed.  While demonstrating NR, let me also show you how to format a little bit of output using print.  Commas between arguments in a print statement put spaces between them, but I can leave out the comma and no spaces are inserted.

awk '{print NR ") " $1 " -> " $(NF-2)}' logs.txt

1) -> 200
2) -> 304

Powerful, but nothing hard yet, I hope.  By the way, there is also a printf function that works much the way you'd expect if you prefer that form of formatting.  Now, not all files have fields that are separated with whitespace.  Let's look at the date field:

$ awk '{print $2}' logs.txt


The date field is separated by "/" and ":" characters.  I can do the following within one awk program, but I want to teach you simple things that you can string together using more familiar unix piping because it's quicker to pick up a small syntax.  What I'm going to do is pipe the output of the above command through another awk program that splits on the colon. To do this, my second program needs two {} components.  I don't want to go into what these mean, just to show you how to use them for splitting on a different delimiter.

$ awk '{print $2}' logs.txt  | awk 'BEGIN{FS=":"}{print $1}'


I just specified that I wanted a different FS (field separator) of ":" and that I wanted to then print the first field.  No more time, just dates!  The simplest way to get rid of that prefix [ character is with sed, which you are likely already familiar with:

$ awk '{print $2}' logs.txt  | awk 'BEGIN{FS=":"}{print $1}' | sed 's/\[//'


I can further split this on the "/" character if I want using the exact same trick, but I think you get the point.  Next, lets learn just a tiny bit of logic.  If I want to return only the 200 status lines, I could use grep, but I might end up with an ip address that contains 200, or a date from year 2000.  I could first grab the 200 field with Awk and then grep, but then I lose the whole line's context.  Awk supports basic if statements.  Lets see how I might use one:

$ awk '{if ($(NF-2) == "200") {print $0}}' logs.txt

Output: [28/Sep/2010:04:08:20] "GET /robots.txt HTTP/1.1" 200 0 "msnbot"

There we go, returning only the lines (in this case only one) with a 200 status.  The if syntax should be very familiar and require no explanation.  Let me finish up by showing you one stupid example of awk code that maintains state across multiple lines.  Lets say I want to sum up all of the status fields in this file.  I can't think of a reason I'd want to do this for statuses in a log file, but it makes a lot of sense in other cases like summing up the total bytes returned across all of the logs in a day or something.  To do this, I just create a variable which automatically will persist across multiple lines:

$ awk '{a+=$(NF-2); print "Total so far:", a}' logs.txt

Total so far: 200
Total so far: 504

Nothing doing.  Obviously in most cases, I'm not interested in cumulative values but only the final value.  I can of course just use tail -n1, but I can also print stuff after processing the final line using an END clause:

$ awk '{a+=$(NF-2)}END{print "Total:", a}' logs.txt

Total: 504

If you want to read more about awk, there are several good books and plenty of online references.  You can learn just about everything there is to know about awk in a day with some time to spare.  Getting used to it is a bit more of a challenge as it really is a little bit different of a way to code - you are essentially writing only the inner part of a for loop.  Come to think of it, this is a lot like how MapReduce feels, which is also initially disorienting.

I hope some of that was useful.  If you found it to be so, leave a comment to let me know, I enjoy the feedback if nothing else.

Update Sep 30, 2010: There are some great comments elsewhere in addition to here.  I wish they would end up in one place, but the best I can do currently is to link to them:

Update Jan 2, 2011: This post caught the interest of Hacker Monthly who republished it in issue #8.  You can grab the pdf version of this article courtesy of Lim Cheng Soon, Hacker News' Founder.

A crash course in PostgreSQL, Part 1

SkyHi @ Monday, August 29, 2011
PostgreSQL is a first-rate, enterprise-worthy open source RDBMS (relational database management system) that compares very favorably to high-priced closed-source commercial databases. Databases are complex, tricksy beasts full of pitfalls. In this two-part crash course, we'll get a new PostgreSQL database up and running with elegant ease, and learn important fundamentals.
['NewSQL' could combine the best of SQL and NoSQL and NoSQL offers users scalability, flexibility, speed]
If you're a database novice, then give yourself plenty of time to learn your way around. PostgreSQL is a great database for beginners because it's well documented and aims to adhere to standards. Even better, everything is discoverable -- nothing is hidden, not even the source code, so you can develop as complete an understanding of it as you want.


The most important part of administering any database is preparation, in planning and design, and in learning best practices. A good requirements analysis will help you decide what data to store, how to organize it, and what business rules to incorporate. You'll need to figure out where your business logic goes -- in the database, in middleware, or applications? You may not have the luxury of a clean, fresh new installation, but must instead grapple with a migration from a different database. These are giant topics for another day; fortunately there are plenty of good resources online, starting with the excellent PostgreSQL manuals and Wiki.


We'll use three things in this crash course: PostgreSQL, its built-in interactive command shell psql, and the excellent pgAdmin3 graphical administration and development tool. Linux users will find PostgreSQL and pgAdmin3 in the repositories of their favorite Linux distributions, and there are downloads on for Linux, FreeBSD, Mac OS X, Solaris, and Windows. There are one-click installers for OS X and Windows, and they include pgAdmin3. Any of these operating systems are fine for testing and learning. For production use, I recommend a Linux or Unix server, because they're reliable, efficient, and secure.
Linux and FreeBSD split PostgreSQL into multiple packages. You want both the server and client. For example, on Debian the metapackage postgresql installs all of these packages:
# apt-get install postgresql
postgresql postgresql-9.0 postgresql-client-9.0 
           postgresql-client-common postgresql-common
See the detailed installation guides on the PostgresSQL wiki for more information for all platforms.
The downloads page also includes some live CDs which make it dead easy to set up a test server; simply boot the CD and go to work. For this article, I used a Debian Wheezy (Testing) system running PostgreSQL 9.0.4, the current stable release.

Creating and destroying a new PostgreSQL database

You'll have to jump through a number of startup and user account hurdles to get started. First, verify that your PostgreSQL server has started by opening psql, its interactive command shell:
$ psql
psql: could not connect to server: No such file or directory
Oops, PostgreSQL is not running. Go back to the appropriate installation guide to see how to start it on your system. On Debian, it starts automatically after installation, so the above command produces the following result:
carla@xena:~$ psql
psql: FATAL:  role "carla" does not exist
Well, excuse me all to heck! But this really isn't a big deal, because PostgreSQL creates a default postgres superuser with no password. So you have to change to this user, and then create a new user account that you will use to administer the database. On Linux and Unix you need to gain rootly powers, like this:
carla@xena:~$ su
root@xena:/home/carla# su postgres
There, now we can get some real work done! Let's create a carla superuser for PostgreSQL:
postgres@xena:/home/carla$ createuser carla
could not change directory to "/home/carla"
Shall the new role be a superuser? (y/n) y
These PostgreSQL roles, postgres and carla, are PostgreSQL user accounts that are independent of system accounts. A role can be a single user or a group of users. Roles can own database objects, such as tables, and can assign privileges to access those tables to other roles. Use the dropuser command to delete a role:
$ dropuser carla
Now, let's create a brand-new database:
$ createdb testdb

No news is good news; if this is successful there will be no feedback. You'll see a message only if something went wrong. Now let's destroy our new database:
$ dropdb testdb

Again, silence equals success.

Exploring PostgreSQL

Start by creating a new database so you have something to work with. There won't be any data in it yet, but that's all right. Once you've created to it, connect to it using the psql command:
$ psql testdb
psql (9.0.4)
Type "help" for help.

Excellent! We are now sitting at the command prompt of our new database. The hash mark indicates that a superuser is logged in. (An angle brace would indicate a less-privileged user.) You would use \q to quit (i.e., testdb=# \q). man psql lists all of the PostgresSQL commands. All commands that begin with a backslash are internal psql commands. They are not operating system shell commands, and they are not SQL commands.
Now, let's list all of our databases. (The last column of the table has been separated out so it'll all fit on the page, but this will be one table on your screen.)
$ testdb=# \list
 List of databases
   Name    |  Owner   | Encoding |  Collation  |    Ctype      
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 
           |          |          |             |             
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 
           |          |          |             |             
 testdb    | carla    | UTF8     | en_US.UTF-8 | en_US.UTF-8 
 |   Access privileges 
 | =c/postgres          +
 | postgres=CTc/postgres
 | =c/postgres          +
 | postgres=CTc/postgres
There's our little testdb down at the bottom. The postgres database holds system data. template0 and template1 are templates for new databases, and template1 is the default. (You can use any Postgres database as a template.) template0 cannot be changed, but template0 can. Let's take a look inside postgres.
$ psql postgres
psql (9.0.4)
Type "help" for help.

Who are the postgres DB users?
postgres=# \du
List of roles
 Role name |            Attributes             | Member of 
 carla     | Superuser, Create role, Create DB | {}
 postgres  | Superuser, Create role, Create DB | {}
What tablespaces do we have?
postgres=# \db
       List of tablespaces
    Name    |  Owner   | Location 
 pg_default | postgres | 
 pg_global  | postgres | 
(2 rows)
Wait, back up: What are tablespaces? That's PostgreSQL's name for the physical storage locations of your database objects on disk. In other words, they're plain old directories on your filesystem. So you can control your disk layout and put your database objects wherever you like; for example, you could put a heavily-used index on a fast disk, or move objects to another partition or disk if you run out of space. Postgres has a squillion built-in objects, such as tables, functions, data types, aggregates, operators, and views. It also supports user-created objects. You can see the objects in the postgres DB, as this abbreviated example shows:
postgres=# \ddS

                      Object descriptions
   Schema   |    Name    |  Object   |      Description                                                   
 pg_catalog | abbrev     | function  | abbreviated display of inet value
 pg_catalog | abs        | function  | absolute value
 pg_catalog | abstime    | data type | absolute, limited-range date and time 
 pg_catalog | aclitem    | data type | access control list
 pg_catalog | bit_and    | aggregate | bitwise-and bigint aggregate
Press the Q key to exit the object descriptions. \dd means "show descriptions of all objects that have descriptions." By default system objects are not shown, so to see these add S.
Postgres is more than a RDBMS; it calls itself an an object-relational database management system, or ORDBMS. This is not the same as a object-oriented database management system (OODBMS), but something of a hybrid, a traditional relational database with an object-oriented database model; it supports objects, classes and inheritance.

Viewing Tables

Let's look at some tables while we're in the postgres DB. First, list its system tables:
postgres=# \dtS
              List of relations
   Schema   |      Name       | Type  |  Owner   
 pg_catalog | pg_aggregate    | table | postgres
 pg_catalog | pg_am           | table | postgres
 pg_catalog | pg_amop         | table | postgres
What's inside the pg_am table?
postgres=# \d pg_am

Table "pg_catalog.pg_am"
     Column      |   Type   | Modifiers 
 amname          | name     | not null
 amstrategies    | smallint | not null
 amsupport       | smallint | not null
 amcanorder      | boolean  | not null
 amcostestimate  | regproc  | not null
 amoptions       | regproc  | not null
    "pg_am_name_index" UNIQUE, btree (amname)
    "pg_am_oid_index" UNIQUE, btree (oid)
This is just the table structure without data. It shows the column names, the data type for each column, and any optional modifiers. Try creating your own table in your test database. For instance, this simple table tracks my underground comics collection:
    name              varchar(80),
    publisher         varchar(80),
    date_published    date
You can copy and paste this right into your own psql prompt:
testdb=# CREATE TABLE comics (
testdb(#     name              varchar(80),
testdb(#     publisher         varchar(80),
testdb(#     date_published    date
testdb(# );
The commas tell psql where your columns end, and the semi-colon tells where your command ends. Try running the commands you've already learned on your test database and new table to see how they look. Use DROP TABLE tablename;
That's all for today. Come back for Part 2 to find out how to populate tables with data, to learn about schema, keys, normalization, views, and tuples, and to discover how to use pgAdmin3.


Learn Vim Progressively

SkyHi @ Monday, August 29, 2011
Vim the Six Billion Dollar editor
Better, Stronger, Faster.
Learn vim and it will be your last text editor. There isn’t any better text editor I know. Hard to learn, but incredible to use.
I suggest you to learn it in 4 steps:
  1. Survive
  2. Feel comfortable
  3. Feel Better, Stronger, Faster
  4. Use vim superpowers
By the end of this journey, you’ll become a vim superstar.
But before we start, just a warning. Learning vim will be painful at first. It will take time. It will be a lot like playing a music instrument. Don’t expect to be more efficient with vim than with another editor in less than 3 days. In fact it will certainly take 2 weeks instead of 3 days.

1st Level – Survive

  1. Install vim
  2. Launch vim
  3. DO NOTHING! Read.
In a standard editor, typing on the keyboard is enough to write something and see it on the screen. Not this time. Vim is in Normal mode. Lets get in Insert mode. Type on the letter i.
You should feel a bit better. You can type letters like in a standard notepad. To get back in Normal mode just tap the ESC key.
You know how to switch between Insert and Normal mode. And now, the list of command you can use in Normal mode to survive:
  • i: Insert mode. Type ESC to return to Normal mode.
  • x: Delete the char under the cursor
  • :wq: Save and Quit (:w save, :q quit)
  • dd: Delete (and copy) current line
  • p: Paste
  • hjkl (recommended but not mandatory): basic cursor move (←↓↑→). Hint: j look like a down arrow.
  • :help : Show help about , you can start using :help without anything else.
Only 5 commands. This is very few to start. Once these command start to become natural (may be after a complete day), you should go on level 2.
But before, just a little remark on Normal mode. In standard editors, to copy you have to use the Ctrl key (Ctrl-c generally). In fact, when you press Ctrl, it is a bit like if all your key change meaning. With vim in Normal mode, it is a bit like if your Ctrl key is always pushed down.
A last word about notation: instead of writing Ctrl-λ, I’ll write .

2nd Level – Feel comfortable

You know the commands required for survival. It’s time to learn a few more commands. I suggest:
  1. Insert mode variations:
    • a → insert after the cursor
    • o → insert a new line after the current one
    • O → insert a new line before the current one
    • cw → replace from the cursor to the end the word
  2. Basic moves
    • 0 → go to first column
    • ^ → go to first non-blank character of the line
    • $ → go to the end of line
    • g_ → go to the last non-blank character of line
    • /pattern → search for pattern
  3. Copy/Paste
    • P → paste before, remember p is paste after current position.
    • yy → copy current line, easier but equivalent to ddP
  4. Undo/Redo
    • u → undo
    • → redo
  5. Load/Save/Quit/Change File (Buffer)
    • :e → open
    • :w → save
    • :saveas → save to
    • ZZ or :wq → save and quit
    • :q! → quit without saving, also :qa! to even if there are some modified hidden buffers.
    • :bn (resp. :bp) → show next (resp. previous) file (buffer)
Take the time to integrate all of these command. Once done, you should be able to do every thing you are able to do on other editors. But until now, it is a bit awkward. But follow me to the next level and you’ll see why.

3rd Level – Better. Stronger. Faster.

Congratulation reaching this far! We can start the interesting stuff. At level 3, we’ll only talk about command which are compatible with the old vi.


Lets look at how vim could help you to repeat yourself:
  1. . → (dot) will repeat the last command,
  2. N → will do the command N times.
Some examples, open a file and type:
  • 2dd → will delete 2 lines
  • 3p → will paste the text 3 times
  • 100idesu [ESC] → will write “desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu “
  • . → Just after the last command will write again the 100 “desu “.
  • 3. → Will write 3 “desu” (and not 300, how clever).


Knowing how to move efficiently with vim is very important. Don’t skip this section.
  1. NG → Go to line N
  2. gg → shortcut for 1G, go to the start of the file
  3. G → Go to last line
  4. Word moves:
    1. w → go to the start of the following word,
    2. e → go to the end of this word.
    By default, word are composed of letter and the underscore character. If you want to use word in the meaning of group of letter separated by spaces, just use uppercases:
    1. W → go to the start of the following “extended” word,
    2. E → go to the end of this “extended” word.
    Word moves example
Now let’s talk about very efficient moves:
  • % : Go to corresponding (, {, [.
  • * (resp. #) : go to next (resp. previous) occurrence of the word under the cursor
Believe me, the last three commands are gold.


Remember about the importance of vi moves? Here is the reason. Most commands can be used using the following general format:

For example : 0y$ means
  • 0 → go to the beginning of this line
  • y → yank from here
  • $ → up to the end of this line
We also can do things like ye, yank from here to the end of the word. But also y2/foo yank up to the second occurrence of “foo”.
But what was true for y (yank), is also true for d (delete), v (visual select), gU (uppercase), gu (lowercase), etc…

4th Level – Vim Superpowers

With all preceding commands you should be comfortable to use vim. But now, here are the killer features. Some of these features were the reason I started to use vim.

Move on current line: 0 ^ $ f F t T , ;

  • 0 → go to column 0
  • ^ → go to first character on the line
  • $ → go to the last character on the line
  • fa → go to next occurrence of the letter a on the line. , (resp. ;) will seek for the next (resp. previous) occurrence.
  • t, → go just before the character ,.
  • 3fa → search the 3rd occurrence of a on this line.
  • F and T → like f and t but backward. Line moves
Some Useful Tips
  • dt" → remove everything until the ".
  • vi" → select everything inside two ".

Select rectangular blocks: .

Rectangular blocks are very useful to comment many lines of code. Typically: 0I-- [ESC]
  • ^ → go to start of the line
  • → Start block selection
  • → move down (could also be jjj or %, etc…)
  • I-- [ESC] → write -- to comment each line
Rectangular blocks
Not on windows you might have to use instead of if your clipboard is not empty.

Completion: and .

In Insert mode, just type the start of a word, then type , magic… Completion

Macros : qa do something q, @a, @@

qa record your actions in the register a. Then @a will replay the macro saved into the register a as if you typed it. @@ is a shortcut to replay the last executed macro.
On a line containing only the number 1, type this:
  • qaYpq
    • qa start recording.
    • Yp duplicate this line.
    • increment the number.
    • q stop recording.
  • @a → write 2 under the 1
  • @@ → write 3 under the 2
  • Now do 100@@ will create a list of increasing numbers until 103.

Visual selection: v,V,

We saw an example with . There is also v and V. Once the selection made, you can:
  • J → join all lines together.
  • < (resp. >) → indent to the left (resp. to the right).
  • = → auto indent
Add something at the end of all visually selected lines:
  • go to desired line (jjj or or /pattern or % etc…)
  • $ go to the end of line
  • A, write text, ESC.
Append to many lines

Splits: :split and vsplit.

Here are the main commands, but you should look at :help split.
  • :split → create a split (:vsplit create a vertical split)
  •  : where dir is any of hjkl or ←↓↑→ to change split.
  • _ (resp. |) : maximise size of split (resp. vertical split)
  • + (resp. -) : Grow (resp. shrink) split


That was 90% of commands I use every day. I suggest you to learn no more than one or two new command per day. After two to three weeks you’ll start to feel the power of vim in your hands.
Then, you will learn about !, folds, registers, the plugins and many other features. Learn vim like you’d learn piano and all should be fine.