Hi! I've just tried to install linuxbrew on two Debian 8.10 systems via
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
I only have user rights on both systems.
On the one system, it went fluently: the linuxbrew asked me whether to install itself to $HOME/.linuxbrew installation or to /home/linuxbrew/.linuxbrew. On the other system, it doesn't offer this choice:
→ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
==> This script will install:
/home/linuxbrew/.linuxbrew/bin/brew
/home/linuxbrew/.linuxbrew/share/doc/homebrew
/home/linuxbrew/.linuxbrew/share/man/man1/brew.1
/home/linuxbrew/.linuxbrew/share/zsh/site-functions/_brew
/home/linuxbrew/.linuxbrew/etc/bash_completion.d/brew
/home/dsumin/.cache/Homebrew/
/home/linuxbrew/.linuxbrew/Homebrew
==> The following new directories will be created:
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/Homebrew
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/share/zsh
/home/linuxbrew/.linuxbrew/share/zsh/site-functions
/home/linuxbrew/.linuxbrew/var
Press RETURN to continue or any other key to abort
Do you have sudo access on the other system? Please report the output of…
sudo -v; echo $?
Do you have write access to any of /home/linuxbrew/.linuxbrew, or /home/linuxbrew or /home? Please report…
ls -ld /home/linuxbrew/.linuxbrew /home/linuxbrew /home
Do you have sudo access on the other system? Please report the output of…
sudo -v; echo $?There is access to the sudo executable, but I will have no additional rights after entering the password (or the executable is not in the sudo white-list).
sudo -v; echo $?
0
Do you have write access to any of /home/linuxbrew/.linuxbrew, or /home/linuxbrew or /home? Please report…
ls -ld /home/linuxbrew/.linuxbrew /home/linuxbrew /homeI have the write access only to my user's home, and there is no
/home/linuxbrewfolder:
ls -ld /home/linuxbrew/.linuxbrew /home/linuxbrew /home
ls: cannot access /home/linuxbrew/.linuxbrew: No such file or directory
ls: cannot access /home/linuxbrew: No such file or directory
drwxr-xr-x 3 root root 0 Jan 22 18:28 /home
The Linuxbrew installer believes incorrectly that you have sudo access and suppresses the prompt.
Please report…
sudo -l mkdir; echo $?
sudo -ln mkdir; echo $?
sudo -l mkdir; echo $?
1
sudo -ln mkdir; echo $?
1
sudo -l
Matching Defaults entries for dsumin on wks-14-18:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User dsumin may run the following commands on wks-14-18:
(root) NOPASSWD: /usr/lib/confupdate/mpi_setxorientation
(root) NOPASSWD: /usr/lib/confupdate/mpi_setxrotation
(root) NOPASSWD: /usr/bin/flush_fs_caches
(root) NOPASSWD: /usr/bin/mpi_backlight
On a system that does have sudo access:
$ sudo -l mkdir; echo $?
/bin/mkdir
0
$ sudo -ln mkdir; echo $?
/bin/mkdir
0
So it looks as thoughsudo -l mkdir is a better test than sudo -v.
I'll have time to look into this issue in about two weeks. In the mean time, you could edit the install script yourself to force it to prompt, or you could use git clone https://github.com/Linuxbrew/brew to install Linuxbrew in a different location. Let me know if you need help with that.
Sure, I'll be able to install Linuxbrew. Thank you for the fast response and developing the project! :)
Just came across this issue as well. Changing this line from
Kernel.system "/usr/bin/sudo", "-v"
to
Kernel.system "/usr/bin/sudo -l mkdir"
successfully bypassed the prompt.
However, I found it confusing that the bypassing is silent. I'd like to submit the change above as a PR, but I'd appreciate some hints regarding how to make the bypassing more intuitive.
In particular, I would think that lines 225-227 should be inside the if sudo? block right underneath them, but I'm not sure the flow would be correct in that case.
Alternatively, we could print out a message next to line 232, saying something like "(automatically picking install directory -- no sudo access)", but that doesn't sound very elegant, so I'd prefer going the other route, if possible.
if sudo? is the line that will display the prompt asking for the sudo password. We want to display the message of lines 225–227 before asking for the sudo password. The message on line 247 prints the chosen installation directory.
https://github.com/Linuxbrew/install/blob/220647fbd8d4b926567ad257b6cc4ea187402d19/install#L247
This line could be improved…
https://github.com/Linuxbrew/install/blob/220647fbd8d4b926567ad257b6cc4ea187402d19/install#L223
if $?.success?
ohai "You can use sudo without a password"
else
…
end
We want to display the message of lines 225–227 before asking for the sudo password.
Just to confirm we're in the same page: if we can test whether there's sudo access and determine that there isn't (without user interaction), then the lines should not be printed, right?
Yes, if we're certain that sudo? won't prompt the user for her password.
Cool. But to be honest, I am a little confused as to how the final code is supposed to look. Are you talking about something like this?...
unless mac?
if File.writable?(HOMEBREW_PREFIX_DEFAULT) || File.writable?("/home/linuxbrew") || File.writable?("/home")
HOMEBREW_PREFIX = HOMEBREW_PREFIX_DEFAULT.freeze
else
Kernel.system "/usr/bin/sudo -n -v 2>/dev/null"
- unless $?.success?
+ if $?.success?
+ ohai "You can use sudo without a password"
+ else
ohai "Select the Linuxbrew installation directory"
puts "- #{Tty.bold}Enter your password#{Tty.reset} to install to #{Tty.underline}#{HOMEBREW_PREFIX_DEFAULT}#{Tty.reset} (#{Tty.bold}recommended#{Tty.reset})"
puts "- #{Tty.bold}Press Control-D#{Tty.reset} to install to #{Tty.underline}#{ENV["HOME"]}/.linuxbrew#{Tty.reset}"
puts "- #{Tty.bold}Press Control-C#{Tty.reset} to cancel installation"
end
if sudo?
HOMEBREW_PREFIX = HOMEBREW_PREFIX_DEFAULT.freeze
else
HOMEBREW_PREFIX = "#{ENV["HOME"]}/.linuxbrew".freeze
end
end
HOMEBREW_REPOSITORY = "#{HOMEBREW_PREFIX}/Homebrew".freeze
end
(sorry, I'm not used to Ruby and am not really versed in the sudo mechanics)
Yes. I think that's probably an improvement over what we have now. What do you think?
I'll have to experiment with the script and see what it does, because to be honest I am having some trouble wrapping my head around the changes here. My first comment above was about changing line 88 from Kernel.system "/usr/bin/sudo", "-v" to Kernel.system "/usr/bin/sudo -l mkdir", but this part of the code does not use that, and instead runs Kernel.system "/usr/bin/sudo -n -v 2>/dev/null". I don't know what the difference is, especially since there's an if sudo? right after that.
I guess I need to research how the passwordless sudo is supposed to work. Or maybe it's just that it's late here, and tomorrow with a fresh head I'll be able to grasp this better. Let me get back to you later. Thanks for the help so far!
I've been going back and forth and testing multiple options. I think I managed to understand the code, but there are several problems here:
It doesn't seem to be possible to silently test for sudo write access: sudo -n -l mkdir produces the return code 1 and prints an error message to stderr, both on a system where I can run sudo mkdir, and a system where I cannot; and sudo -v is not reliable for that because of the issue mentioned above (and further detailed here)
So it seems we can only proceed silently with the default prefix if it is writable as-is; the block
Kernel.system "/usr/bin/sudo", "-v"
unless $?.success?
# prompt messages
end
is useless, and we might as well just remove it.
However, if we do remove it, we must ensure that a password prompt indeed appears after the printed options, otherwise it makes no sense to present them to the user. To do that, we can run Kernel.system "/usr/bin/sudo -k" before the sudo? call, to ensure it will prompt the user.
But in a system with no sudo mkdir access, sudo -l mkdir will simply fail silently, without prompting the user. So we still have the problem of the messages appearing without providing an actual option.
There doesn't seem to be a way to distinguish this situation from the case where the user has sudo mkdir access, but then types Ctrl+D at the prompt; in both cases, nothing will be sent to stdout or stderr, and the return code will be 1. And if we can't distinguish these situations, we can't tell the user why the local install was automatically picked. It's important to tell them this because they were offered a choice, with instructions on how to select one, and then the script didn't wait for them to actually follow those instructions.
The only solution I can see to this conundrum is if we were somehow able to detect whether sudo presented a prompt to the user. Then we could distinguish the two cases above, and present reasonable output for everyone. Do you know if this is possible?
It doesn't seem to be possible to silently test for sudo write access:
sudo -n -l mkdir
sudo -n -l mkdir tests whether the user has passwordless sudo access.
To do that, we can run Kernel.system "/usr/bin/sudo -k" before the sudo? call, to ensure it will prompt the user.
Sounds good to me.
The only solution I can see to this conundrum is if we were somehow able to detect whether sudo presented a prompt to the user.
sudo has the -p option to present a prompt to the user. Perhaps we can use the bash-ism $"hello\nworld\n` to include line breaks in the prompt. It may make it non-portable to Dash, the default shell on Debian. Perhaps there's a portable way to include line breaks.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
PR created to resolve this at Linuxbrew/install#36