I was just writing a C++ program on my Ubuntu 14.10 computer. As it is a client/server program, I has three terminal emulators open: one for writing code and compilation, one for client testing, and the last one for server testing. After a while, I thought I had a bug in my code. I lost over an hour tracking it down, and it turned out that getting out of directory and entering it again solved the whole problem. To be precise these were the commands I executed:
some_directory$ ./client some_directory$ cd .. $ cd some_directory some_directory$ ./client
Without changing anything—and without recompilation—the two runs gave different results. The only thing I can think of is some kind of cache that would store old version of files, but I never heard about such a feature. Is there an explanation, and how to solve it (make it refresh automatically, without exitting directory)?
I don’t think bash does anything that fancy (it does cache paths to executables specified without paths, but that doesn’t apply here, since you are specifying the path)
Sounds like the directory you were in was moved or mounted over. In the case of building software, the directory move is more likely.
Directory move case
An example of recreating the behaviour of a directory move, in terminal 1
cd /tmp mkdir dir1 cd dir1 touch exampleFile
Then in terminal 2:
cd /tmp mv dir1 dir2 mkdir dir1 cd dir1
Both shells show as being in a directory named ‘dir1’, but a listing will show different contents. If terminal2 creates a file called ‘exampleFile’, both shells will show ‘exampleFile’ in ‘dir1’ but they are different files. This is because the shell in terminal 1 is in fact in dir2 now, it just doesn’t know it. The shell in terminal 1 can get to the real ‘dir1’ via cd:
This looks weird but re-resolves the path.
Over mount case
This occurs when a shell (or any program) is in a directory and then a filesystem is mounted over top of it. For example, in terminal 1:
mkdir /tmp/dir1 cd /tmp/dir1
mount /dev/whateverdev /tmp/dir1 cd /tmp/dir1
Terminal 1 sees the files from the original filesystem in that directory. Terminal 2 sees the files from /dev/whateverdev.
How to avoid
In the case of over mounting, this is mostly just being aware of what you are doing or how your machine is configured (for example, if an automounter is running when a usb drive is plugged in).
In the case of directory moves, this depends a bit more on the build system. If there is a rule that makes a backup of the old output directory by moving it and then creates a new directory for the new build, you’ll run into this situation quite frequently. Check your build rules for trickery.
Of course, this could also have been a one-time unintentional accident (similar to what was shown in the first example above). In which case, awareness that this can happen will help you out.
hash – built in command of bash
To speed up the operation when you execute a command the bash shell store its path in an hash table. Each
shell instance has its own
hash table. For more information read this excerpt from
If the name is neither a shell function nor a builtin, and contains no
slashes, bash searches each element of the
PATHfor a directory
containing an executable file by that name.
Bash uses a hash table to remember the full pathnames of executable files (see
hashunder SHELL BUILTIN COMMANDS below). A full search of the directories in
PATHis performed only if the command is not found in the hash table.
You can substitute an entry in the list (e.g. the command
hash client; you can erase this entry from the list with
hash -d client; you can reset the list completely with
Sync– Synchronize data on disk with memory
sync command ensures everything in memory is written to disk.
To speed up the operation often Linux can store some data in the kernel filesystem buffers, i.e., data which has been scheduled for writing via low-level I/O system calls.
On the other hands “Hard disks may default to using their own volatile write cache to buffer writes, which greatly improves performance while introducing a potential for lost writes”
syncwrites any data buffered in memory out to disk. This can
include (but is not limited to) modified superblocks, modified inodes,
and delayed reads and writes. This must be implemented by the kernel;
syncprogram does nothing but exercise the `sync’ system call.
The kernel keeps data in memory to avoid doing (relatively slow)
disk reads and writes. This improves performance, but …
[if you are interested continue to read here or with
info coreutils sync].
Specific to your problem
If your problem depends on one of the aspects above you can try to write in only one line more than one command, and after quick recall them with the up arrow key, e.g.:
hash -d ./client; ./client,
sync ; ./client,
hash -d ./client ; sync ; ./client
(cd .. ; cd - ; ./client ), your own solution. Here you execute the client in a subshell that take in heritage all you have done in your shell (as variables…) but that will not return changes to the current shell.
Without a complete understanding of the operations involved in your compilation steps and in the dialling operation between client and server can be difficult to find the cause (it can even be a symbolic link, or an high latency on a NFS filesystem …). In this case you have to search the origin by trials and errors.