Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running intermediate try scripts with the original shell #7

Open
angelhof opened this issue May 24, 2023 · 3 comments
Open

Running intermediate try scripts with the original shell #7

angelhof opened this issue May 24, 2023 · 3 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@angelhof
Copy link
Member

angelhof commented May 24, 2023

try currently runs the intermediate temporary scripts that it creates using /bin/sh. This causes a problem if we want the internal script to run using a different shell and therefore inherit its state, e.g., bash functions.

A running example of the wanted behavior follows:

$ func() { echo hi; }
$ export -f func
$ bash ./deps/try/try func
hi

I think that a good portable solution would be to run the intermediate scripts with whatever shell try is running too. What is a portable way to determine which shell we are running on? Here are some alternatives:

  • The $SHELL variable will contain the name of the login shell (it doesn't work if the subprocess is different than the login shell)
  • Using ps, e.g., ps -o args= -p "$$" or ps -o command= -p "$$". This seems to me like the most portable and correct solution.

Here are some SO posts that discuss this issue:

Note that we don't really care about the underlying shell, we just want the executable (or even a link to it), so if try was invoked using /bin/sh we can just use that, we don't care that it was bash under the hood.

@angelhof
Copy link
Member Author

@mgree and @dspinellis any thoughts? I can implement the ps solution, I just need a second opinion on whether it is adequately portable :)

@dspinellis
Copy link

dspinellis commented May 25, 2023

I don't think the ps way is accurate enough, because it gives the name of the command that invoked the shell, but not the actual shell path. For example, if I execute a script with sh script I will get sh without a path, and won't know whether this is a link to, say, bash or sh. Here are the ways I recommend for commonly used systems.

  • For Linux I recommend using stat --format='%N' /proc/$$/exe, which will output something like '/proc/3339774/exe' -> '/bin/bash'
  • For FreeBSD I recommend using procstat -bh $$, which will output something like 78297 sh 1400073 /bin/sh (we need to use all fields after the third to take into account spaces in paths)
  • On macOS consider using lsof -p $$ -Fnf | sed -n '/^ftxt/{n;/dlyd/d;s/^n//;p;}' (The sed command prints the output of txt entries, removing the dynamic loader entry, which I've seen appear in older macOS versions).

@mgree
Copy link
Contributor

mgree commented May 25, 2023

I agree that ps doesn't quite cut it. These detection approaches seem good; we should also have a flag that lets you pick the shell that runs.

Also: these APIs only exist on Linux and FreeBSD, so we don't need to worry about macOS portability.

@mgree mgree added enhancement New feature or request good first issue Good for newcomers labels Jun 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants