When a command runs a second time, ksh re-walks the $PATH in full even though the previous lookup is already cached as a tracked alias. This has no functional impact, but would be a good performance improvement if the caching is honored.
d=$(mktemp -d)
for s in bash mksh zsh ksh93; do
echo "===== $s ====="
PATH="$d:/usr/bin:/bin" strace -f -e trace=execve,newfstatat "$s" -c '
echo "-- FIRST RUN --" >&2
ls >/dev/null 2>&1
echo "-- SECOND RUN --" >&2
ls >/dev/null 2>&1' 2>&1 | grep -E "^-- (FIRST|SECOND)|\"[^\"]*/ls\""
echo
done
rmdir "$d"
===== bash =====
-- FIRST RUN --
newfstatat(AT_FDCWD, "/tmp/tmp.NXIp9QJ7Ls/ls", 0xffffef373208, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
[pid 161640] execve("/usr/bin/ls", ["ls"], 0xaaaad6fe2430 /* 79 vars */) = 0
-- SECOND RUN --
[pid 161641] execve("/usr/bin/ls", ["ls"], 0xaaaad6fe2430 /* 79 vars */) = 0
===== mksh =====
-- FIRST RUN --
newfstatat(AT_FDCWD, "/tmp/tmp.NXIp9QJ7Ls/ls", 0xffffffb844d8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
[pid 161653] execve("/usr/bin/ls", ["ls"], 0xaaaadf2d97c8 /* 80 vars */) = 0
-- SECOND RUN --
[pid 161681] execve("/usr/bin/ls", ["ls"], 0xaaaadf2d9cf8 /* 80 vars */) = 0
===== zsh =====
-- FIRST RUN --
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
[pid 161686] execve("/usr/bin/ls", ["ls"], 0xaaaacff7f000 /* 82 vars */) = 0
-- SECOND RUN --
execve("/usr/bin/ls", ["ls"], 0xaaaacff7f000 /* 82 vars */) = 0
===== ksh93 =====
-- FIRST RUN --
newfstatat(AT_FDCWD, "/tmp/tmp.NXIp9QJ7Ls/ls", 0xffffdedd5ca8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 161694] execve("/usr/bin/ls", ["ls"], 0xaaab0b5690e8 /* 81 vars */) = 0
-- SECOND RUN --
newfstatat(AT_FDCWD, "/tmp/tmp.NXIp9QJ7Ls/ls", 0xffffdedd5ca8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, 0) = 0
newfstatat(AT_FDCWD, "/usr/bin/ls", {st_mode=S_IFREG|0755, st_size=199680, ...}, AT_SYMLINK_NOFOLLOW) = 0
execve("/tmp/tmp.NXIp9QJ7Ls/ls", ["ls"], 0xaaab0b5690d8 /* 81 vars */) = -1 ENOENT (No such file or directory)
execve("/usr/bin/ls", ["ls"], 0xaaab0b5690d8 /* 81 vars */) = 0
When a command runs a second time, ksh re-walks the $PATH in full even though the previous lookup is already cached as a tracked alias. This has no functional impact, but would be a good performance improvement if the caching is honored.
Comparative reproducer:
Output (On 1.0.10/Debian):
Also, there appears to be a redundant
execveon the first PATH entry in the second run, even though the binary is not present at that location.