Bugzilla – Bug 133808
'which' doesn't follow the movement of executable
Last modified: 2005-11-21 15:56:46 UTC
1. Login as root. 2. Unzip 'tidy' into /root/bin 3. Do a 'which tidy' -> shows /root/bin/tidy 4. Execute tidy no problem 5. Do a 'mv bin/tidy /usr/bin' 6. Do a 'which tidy' again -> still shows /root/bin/tidy 7. Try to execute tidy by typing just 'tidy' -> shows 'bash: /root/bin/tidy: No such file or directory' Note: /usr/bin is in my path. I can execute other executables in /usr/bin no problem (just by typing the file name only).
I was not able to reproduce this bug. What release of SL 10.0 did you use? Works fine with the final.
I downloaded SL from: http://www.opensuse.org/Released_Version I assume that's the "final" version. And yes, I'm sure it's SL 10.0 By the way, I found that the path to the executable only becomes 'fixed' after you run the executable once. That is, if you move the executable around without ever running it, 'which' always shows the correct path. It's only after you run it the path gets 'cached' somehow. Try moving it AFTER you execute the file once, hopefully you can reproduce the bug that way.
Yes. That is so. The problem here is that the shell keeps a cache about the recently executed commands so that it needn't search the whole path over and over again. This will only affect the builtin `type', though. The external command will always do a real search: mgross@targ:~> type -all which which is aliased to `type -p' which is /usr/bin/which The alias will have the preference before the external program /usr/bin/which here. Typing only `which' calls `type -p` therefore. This cache of the bash can be shown with `hash' and it can be emptied with `hash -r` after which a real search is done. Alternatively the external which can be called explicitly (stating the whole path or using quotes, which will do the same thing here. Here are the commands I tested this with for a better understanding: targ:~ # echo -e '#!/usr/bin/perl\n' > /usr/bin/testfile.pl && chmod +x /usr/bin /testfile.pl targ:~ # which testfile.pl /usr/bin/testfile.pl targ:~ # "which" testfile.pl /usr/bin/testfile.pl targ:~ # testfile.pl targ:~ # mv /usr/bin/testfile.pl /bin targ:~ # which testfile.pl /usr/bin/testfile.pl targ:~ # "which" testfile.pl /bin/testfile.pl targ:~ # hash hits command 2 /usr/bin/which 1 /sbin/preload 2 /bin/chmod 2 /usr/bin/testfile.pl 2 /bin/mv 2 /usr/sbin/grub 1 /usr/bin/whoami 3 /usr/bin/vi targ:~ # hash -r targ:~ # which testfile.pl /bin/testfile.pl targ:~ # "which" testfile.pl /bin/testfile.pl This setup (alias goes before external) is a bash-behaviour that cannot be changed AFAIK. One would have to remove the alias or state exactly what shall be executed (as seen above). This is no bug, it's the same thing in 9.3. You're free to change this, of course. Werner: Can you provide any comment here? Maby we should change the default setup here? Please decide what should be done.
Just a thought: Shouldn't type at least verify the existance of the file before using the cached value? This wouldn't take much time and would be more sound I think. A patch would be in order.
I'd like not to change the default, any admin should be able to call `rehash' or `hash -r'. On the other side, the bash chould check the existence of a program in path and if not found run a rehash ... but this may cause trouble in a NFS environment if the NFS server is temporary not reachable.
Thanks Michael. I'll just remove the alias then.
Using now a shell function which checks the existence of the file and if required runs `has -r'.
Nick: You're welcome. And thanks to Werner.