Live data from Hacker News

Path Isn't Real on Linux

blog.danielh.cc

31–40 of 120 posts

Re: Path Isn't Real on Linux

#31
post #25

Fun fact: if you've ever had bash (or another shell) complain that a file doesn't exist, even though it's on $PATH, check if it's been cached by `hash`. If the file is moved elsewhere on $PATH and bash has the old path cached, you will get an ENOENT. The entire cache can be invalidated with `hash -r`.

Wtf. TIL about hash.

Re: Path Isn't Real on Linux

#32
post #7

Why would strace cat be useful here? By the time cat runs, it was obviously already found. It is basic knowledge that PATH is used by a command interpreter to locate the pathname of binaries. This is true for Window's cmd.exe as well. I never heard of a system where locating files for execution was performed by a kernel.

In the [exec][1] family of POSIX functions, if the command path doesn't contain a slash, then it's looked up in the PATH.

> If the file argument contains a slash character, the file argument shall be used as the pathname for this file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable PATH [...]

[1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/ex...

Re: Path Isn't Real on Linux

#33
post #25

Fun fact: if you've ever had bash (or another shell) complain that a file doesn't exist, even though it's on $PATH, check if it's been cached by `hash`. If the file is moved elsewhere on $PATH and bash has the old path cached, you will get an ENOENT. The entire cache can be invalidated with `hash -r`.

Ah, so that's where sudo texhash -r comes from when installing a latex package!

Re: Path Isn't Real on Linux

#34
post #12

Path globbing, pipes, redirection, job control (fg/bg), and all shell variables -- not just $PATH -- are all handled by the shell. The kernel has no idea what the current process' environment $PATH is, and doesn't even parse any process environment variables at all.

PATH isn't just handled by the shell though. Many (but not all!) of the exec* family of functions in libc respect PATH.

Those functions aren't the real system calls provided by Linux, they're just glibc wrappers with added functionality. Linux kernel execve has absolutely no concept of PATH, it just opens the file at the provided pathname. That's a good thing too, user space might want to customize that stuff.

Re: Path Isn't Real on Linux

#35
The title is nonsense. PATH is the name of an environment variable (a Real Thing(TM)) which lists a set of directories to search for an executable. It is used by shells (including those running on Linux) to locate an executable when the full path to the executable is not supplied by the user.

This is needed because the exece()/execve() [2] kernel system call is unaware of things like environment variables so it will not have any idea how or where to execute a program 'cat' unless it is given the full path to 'cat', so the shell has to look it up (again if the user doesn't pass the full path). It's the same on every POSIX system and the original UNIXes. It's been this way for at least 50 years. (edit 60 years, it's from Multics [1])

Kids today really need to learn the fundamentals of computer operating systems. Or do that boring old-person thing we did before StackOverflow, and read all the manual pages, which tell you all this [3] [4].

[1] https://en.wikipedia.org/wiki/PATH_(variable) [2] https://man7.org/linux/man-pages/man2/execve.2.html [3] https://www.man7.org/linux/man-pages/man1/dash.1.html [4] https://www.man7.org/linux/man-pages/man1/intro.1.html https://www.man7.org/linux/man-pages/man2/intro.2.html https://www.man7.org/linux/man-pages/man7/man-pages.7.html https://www.man7.org/linux/man-pages/man7/standards.7.html

Re: Path Isn't Real on Linux

#36
post #7

Why would strace cat be useful here? By the time cat runs, it was obviously already found. It is basic knowledge that PATH is used by a command interpreter to locate the pathname of binaries. This is true for Window's cmd.exe as well. I never heard of a system where locating files for execution was performed by a kernel.

True... `strace bash -c cat` would give more the series of stat calls they're intending to see:

newfstatat(AT_FDCWD, ".", {st_mode=S_IFDIR|0700, st_size=4096, ...}, 0) = 0

newfstatat(AT_FDCWD, "/usr/local/sbin/cat", 0x7fffcec2f3b8, 0) = -1 ENOENT (No such file or directory)

newfstatat(AT_FDCWD, "/usr/local/bin/cat", 0x7fffcec2f3b8, 0) = -1 ENOENT (No such file or directory)

newfstatat(AT_FDCWD, "/usr/sbin/cat", 0x7fffcec2f3b8, 0) = -1 ENOENT (No such file or directory)

newfstatat(AT_FDCWD, "/usr/bin/cat", {st_mode=S_IFREG|0755, st_size=68536, ...}, 0) = 0

Re: Path Isn't Real on Linux

#37
post #20
post #12

Earlier quoted context omitted.

PATH isn't just handled by the shell though. Many (but not all!) of the exec* family of functions in libc respect PATH.

It seems too far to go to say that because a system library holds some implementation details that the responsibility doesn't lie with the program using them. There's all sorts of complex interdependent details that make those kind of boundary distinctions difficult in many operating systems.

On Linux the main boundary between user space and kernel is quite clear: the system call layer. It is stable and well documented.

https://github.com/torvalds/linux/blob/master/Documentation/...

System libraries like glibc are not part of the kernel, they are just components that can be replaced.

I wrote an article about it:

https://www.matheusmoreira.com/articles/linux-system-calls

I even asked Greg Kroah-Hartman about it:

https://old.reddit.com/r/linux/comments/fx5e4v/im_greg_kroah...

> So we rely on different libc projects to provide this, and work with them when needed.

> This ends up being more flexible as there are different needs from a libc, and for us to "pick one" wouldn't always be fair.

> And yes, you can just use a "nolibc" type implementation of you like.

> I know I do that for new syscalls when working on them, there's nothing stopping anyone else from doing that as well.

You can trash the entire GNU system and rewrite it all in Rust or Lisp if you wanted. It doesn't have to be some POSIX-like thing either, it could be whatever you wanted it to be. It doesn't need to have things like PATH. You could write a static freestanding application and boot Linux directly into it.

Nobody does stuff like this it's a lifetime of work. But it could be done.

Re: Path Isn't Real on Linux

#38
post #25

Fun fact: if you've ever had bash (or another shell) complain that a file doesn't exist, even though it's on $PATH, check if it's been cached by `hash`. If the file is moved elsewhere on $PATH and bash has the old path cached, you will get an ENOENT. The entire cache can be invalidated with `hash -r`.

Is this an old behavior? I would think ENOENT would invalidate the cache entry at least.
Post reply on HN