Developer Tips

    • Always do your checkout's and checkin's on the same type of system as where the code will run. Some companies will force their developers to run windows on their desktop even though they're writing code to run on a Linux or Unix server. With that in mind, I'm suggesting that you DO NOT checkout and checkin code for the Linux and Unix applications from your windows desktop! If you do, then beware of the CRLF problem that windows will do to your Linux files, effectively corrupting the files when checked out on Windblows. The linux command dos2unix will translate the CRLF codes to newlines. But avoid the problem in the first place. Either petition your management to give you the right tools for the job (i.e. a Linux desktop), or don't ever checkout or checkin Linux files from windows.

    • Okay, so you staged an office riot over having a Linux desktop, and the desktop support manager sited some obscure fictional policy that stated that the windows software was secured for desktop use and Linux was not. ?? Go figure, windows more secure that Linux?? *ROFLMAO**** So you're stuck. Fear not, goto http://www.cygwin.com/ and download the setup.exe program. Cygwin is an open source project hosted by redhat. It provides a simulated Linux environment. Yes, X is included, you can even open an xterm on your local desktop that is connected via ssh to some remote Linux or Unix server. Don't waste your money on Exceed. It runs poorly and is overpriced. You can configure your cygwin environment so that it looks like your login account on your Unix systems. As an added bonus, you can install the cygwin cvs or svn packages, checkout files using cygwin, do edits and check everything back in, and you don't get the windows CRLF bug! You don't need administrator priviledges to install cygwin (setup.exe), but you will if you want to run any services. Ya, you could even fire up an sshd under cygwin, and ssh to your desktop! I'll include a script I run, after xstart on my windows desktop, that creates a little GUI window with buttons that will ssh & xterm a session over to a named host:

#!/usr/bin/wish

# vi:set nu ai ap smd showmatch tabstop=4 shiftwidth=4:

# Name: cygterms

# Author: Tom Sandholm

# Version: 1.0

# Date: Fri Jan 5 09:47:47 EST 2007

# Summary: simple gui application to open ssh sessions to

# remote systems.

# pickup the DISPLAY variable

# NOTE: this is only declared if cygwin startxwin has been run

# (X is running).

global D

set D $env(DISPLAY)

global BUTTON_NUMBER

set BUTTON_NUMBER 1

# function to create a button

proc NewButton {Label UserName HostName} {

global BUTTON_NUMBER

global D

# chop out the username & hostname from the button label

#

set tmp [split "$Label" "\n"]

set user [lindex $tmp 0]

set rhost [lindex $tmp 1]

button .b${BUTTON_NUMBER} \

-text "$Label" \

-command "exec xterm -title \"${user}_${rhost}\" -n \"${user}_${rhost}\" -display $D -sb -fn 7x14 -e ssh -Y ${UserName}@${HostName} &"

pack .b${BUTTON_NUMBER} -expand true -fill both -side left

incr BUTTON_NUMBER

}

# local windows (xterms)

# these lines create some local buttons; different colors...

button .d -text "local\nblack" -command "exec xterm -title \"local_black\" -n \"local_black\" -display $D -sb -fn 7x14 &"

pack .d -expand true -fill both -side left

# remote xterms

# NOTE: First argument is the button label.

# Label is to be formatted as "username\nhostname",

# with a "\n" separating the username from hostname".

# 2nd arg is the username to perform the ssh as.

# 3rd arg is the remote hostname.

# syntax: NewButton "label" "username" "hostname"

NewButton "sandholm\nscm-lnx" "someuser" "scm-lnx"

NewButton "sandholm\nscmdr-lnx" "someuser" "scmdr-lnx"

NewButton "sandholm\nsys1-lnx" "someuser" "sys1-lnx"

NewButton "sandholm\nsys2-lnx" "someuser" "sys2-lnx"

NewButton "sandholm\nbeast2" "someuser" "beast2.homelinux.net"

NewButton "sandholm\nsys1-sun" "someuser" "sys1-sun"

NewButton "sandholm\nsat1-lnx" "someuser" "sat1-lnx"

NewButton "sandholm\ntest3-lnx" "someuser" "test3-lnx"

NewButton "sandholm\ntest4-lnx" "someuser" "test4-lnx"

NewButton "sandholm\nbaodev-lnx" "someuser" "baodev-lnx"

NewButton "sandholm\nldap1-lnx" "someuser" "ldap1-lnx"

    • Tip from my Buddy Jey: Instead of installing cygwin, you could install xming. This is a windows package that implements an X server and protocol under the windows environment. It's very easy to install, and worked flawlessly with ssh clients such as putty. Of course you'll not have a *nix like environment such as what cygwin will give you, but to just run ssh with X forwardarding, it's an excellent choice.

    • There's another option for getting a Linux environment on your windows desktop. Install vmware. Of course I'm talking about the free workstation version. And be forewarned, your performance will suffer! Try to do any work on the vmware guest that is running and you'll start seeing clock time issues. But it's better than nothing and vmware has helped out on some occasions when I needed to boot a Linux installation dvd ISO or test our network install server and do a PXE boot.

    • Try to use the shell that is the default for the system. For Linux that's bash. The C shell just doesn't compare to the flexibility of bash. The Korn shell is fine if you're working on a Solaris or AIX system but on Linux the pdksh is lame and doesn't have the same features. Besides, if you're going to be developing some system service it makes sense to run that service the same way as Linux starts it's services, via bash. As a developer, if you're prototyping some code in script, use bash, not zsh or tcsh or some obscure little shell that none of the community uses. You don't want to be stuck supporting the thing for the rest of your life. If you write it in a shell that a majority of the community uses you stand a better chance of passing the support over to a junior developer.

    • Use ulimit to control the execution of your programs. If you've never heard of ulimit check the bash man page and look for ulimit. This is a shell builtin command (it's called limit for csh users). You can control the amount of virtual memory, number of child processes and number of file descriptors just to name a few resources. I'm sure none of us have ever written code that ran off into an infinite loop and spawned thousands of children. If you've had the opportunity I'm sure you made fast friends with the support group! ;-) Just putting in a ulimit at the beginning of your script, or for you C programmers adding a setrlimit system call will help. This will keep your program from trashing the system and save you the embarrassment.

    • I can understand the desire to get the latest versions of library XYZ and writing your application to use it, but consider the environment in which your application will run. If you're using SuSE version 10.0 in production, which came out a couple of years ago, and you've just downloaded the latest, brand-spanking, shiniest library package, just released last week, don't expect it to be supported in production. Try to stay within the limits of the supported packages available in the release of Unix /Linux running in production. Your support staff will be more inclined to respond positively to your request for software install.

    • If you're building an application to deploy on Linux package that program and all it's necessary files into an RPM (RedHat Package Manager). See http://www.rpm.org/ and http://www.rpm.org/max-rpm/.

    • Learn to use the strace command to debug and profile your programs. Take a look in my troublshooting section for examples, Trouble Shooting.

    • If you're building a new application from scratch take a look at the autoproject package, http://directory.fsf.org/project/autoproject/. It's available in the Debian distribution with ports for rpm based systems.

    • Use version control to save all your files. I'd suggest using subversion rather than cvs. Cvs doesn't autodetect your file types and if you're checking in binary files cvs will incorrectly tag them and will try and run diff's on them. This can cause corruption or just really slow checkouts. By default subversion will encourage you to use a good structure for your source tree. You'll normally have directories called trunk (which is your main, latest development branch), branches for your branches, and tags for your tags. When you get ready to release you should always branch from the trunk. You then apply fixes for that release to the newly created branch and may merge those fixes from the branch back into the trunk. We use tags to indicate sucessful compiles of code from trunk. See the subversion article on repository layout, http://svnbook.red-bean.com/en/1.4/svn.reposadmin.planning.html#svn.reposadmin.projects.chooselayout

    • Okay, here's one issue (I'm sure there's more) with using subversion over cvs. Subversion doesn't really allow you to permanently delete files and directories, easily. It all has to do with links and copy-on-write (COW). In order to permanently delete something in subversion, you must:

      1. export the repository.

      2. write a filter to remove the directory/files you wish to delete.

      3. delete the existing repository.

      4. re-create the repository.

      5. import the new "filtered" repository.

A real pain-in-the-ass in comparison to CVS, where you could just delete the directory or files directly.

    • Even if your project doesn't require any compiled code you should still use Makefiles to automate the packaging and testing of your project. You should also put all your testing scripts in subversion, with a Makefile target that will allow you to do automated testing. But as a caution, if your Makefile requires the use of ruby, do NOT put a copy of ruby in your source tree. It's wasteful of the version database, causes headaches for the repository administrator, locks you in to a particular version, and worse, if the utility is a compiled program for an i386 based system, good luck trying to get it to run on a powerpc or arm processor. It's bad practice. Also, do NOT use full pathnames to call these tools, such as ruby. Let the system determine the location of your external tools. If the system doesn't have a tool you need, put in a software request to your Unix support group. They'll get the supported version from the OS distribution and install it for you. Your Makefile should have standard targets, such as "all" (build everything), "clean" (clean up), "dist" (create a distribution - probably an RPM), "test" (run the test suite). If you do this, then your build-and-release team can take over the building and packaging of your project. This is best practice. You never have development do the build-and-release of production code. The build-and-release team is there as a stop-gap, they'll ensure the build environment matches production. The same thing goes for QA. Often the build-and-release team works directly with the QA team. The QA team will also ensure the testing environment matches exactly the production environment.

    • Let me rant about an issue with building Java applications. The build tool for compiling java is ant. Ant does a fine job compiling, packaging and testing java applications. It does a miserable job at interfacing with the host OS. Therefore, you should still use Makefiles for your java projects. Make was designed to integrate nicely with the host OS. You can still setup Makefile targets to call ant. Your build-and-release team will be easier to work with if you follow the norm of using Make. Of course if you're using some java automatic build tool such as anthill or hudson, then the issue become moot, and those utilities will automatically manage the checkout, versioning, build and deployment of your java application.