Closed dbeecham closed 8 years ago
Thank you for reporting this issue.
Currently fizsh only runs as a login shell if it is explicitly invoked as "fizsh -l" or "fizsh --login". Your ssh session calls fizsh without the l flag. This explains why the new instance of fizsh behaves as a non-login shell. This means that "zprofile" is not sourced. On Arch this means in turn that /etc/profile is not sourced either (see https://wiki.archlinux.org/index.php/zsh). The result on Arch is that no $path is set when fizsh is started, which explains the reported message.
Most other distros do not have this problem, because their zsh does not depend on $path being set in /etc/profile.
The issue can indeed be circumvented by manually sourcing zprofile before $(type fizsh) is evaluated.
All right, I have tried around with --login, but I cannot seem to quite figure it out.
Firstly, I cannot set /usr/local/bin/fizsh --login
as shell in /etc/passwd
; doing to gives me an error shell /path/fizsh --login does not exist
. Not sure if I should add this to /etc/shells
, of if I need to escape spaces in passwd, or if this just does not work. So, I created a script:
$ cat /usr/local/bin/fizsh-local
#!/usr/bin/env zsh
echo $PATH
/usr/local/bin/fizsh --login
I also added a echo $PATH
at the top in fizsh.
/usr/bin:/bin:/usr/sbin:/sbin
Is the PATH echoed. So $PATH
is not empty. But /usr/local/bin
isn't added before /etc/profile
is sourced. Also, --login
in /usr/local/bin/fizsh-local
did not work.
I am reading though the source code, trying to understand how to solve the problem. type fizsh
is called on line 58. The only reference to --login is on line 148, but it falls into the same condition as no arguments. Am I missing something?
Around line 170 you will find:
if [[ ( $@ == "" ) ]]; then zsh else zsh -l fi
So, if fizsh is invoked with a command-line argument (which in this case must be -l or --login) then it is started as "zsh -l" (after setting $ZDOTDIR and some other things).
At this moment I do not have an arch machine to test things. I have one at home. I will look into it later.
Ah, I see. The shell is exiting at line 59 though. Should some code be moved around?
But /usr/local/bin isn't added before /etc/profile is sourced.
So /usr/bin is in your path. In that case you could install fizsh as /usr/bin/fizsh. Try something like:
user@localmachine$ ./configure --bindir=/usr/bin
Some further thought:
The script /usr/bin/fizsh (in your case /usr/local/bin/fizsh) is initially invoked as a non-login shell. This makes difficult to determine whether the eventual fizsh shell should be run as a login-shell or not. Because of this fizsh requires the "-l" or "--login" option in order to be started as a login shell.
Yet, after using "ssh -l user@...", "sudo -iu user" or "su -i user", you should get a login shell as well. As you already noted, the problem is that in this case the system logs you in through the /etc/password file, which makes it difficult to provide the -i flag.
If we don't find a proper solution, I will add a note about this in the manpage in the "BUGS" section.
Even if fizsh is started with the --login
argument, the shell will still fail, though? The flag is not used until the call to zsh, $(type fizsh) will be empty anyway.
I can see the issue, though. zsh
should be doing the sourcing, but it can't do it before fizsh
has set up all it needs to, but it can't set it up before zsh
has done the sourcing. It's a catch 22.
I also just realized my line numbers are different from yours since I edited the file.
A thought; is it possible to use $0?
Even if fizsh is started with the --login argument, the shell will still fail, though? The flag is not used until the call to zsh, $(type fizsh) will be empty anyway.
If fizsh is installed as /usr/bin/fizsh
and if /usr/bin
is part of your path $(type fizsh)
will yield /usr/bin/fizsh
. This is how fizsh works by default on Debian.
If /usr/local/bin
is added to the path at the same time as /usr/bin
things will work as well.
Wouldn't you encounter similar problems if zsh is only installed in /usr/local/bin
and /usr/local/bin
is not part of the path? Or what if zsh is only installed in /usr/bin
(as is the case on e.g. Debian) and /usr/bin
is not part of the path?
$ zsh -fd
% echo $path
/usr/local/bin /usr/bin /bin /usr/bin/X11 /usr/games
% path="/usr/local/bin /bin /usr/bin/X11 /usr/games"
% zsh
zsh: command not found: zsh
Merged with the above comment
Removed... Have to look at $0 once more.
zsh actually distinguishes two types of login shells: (1) shells started by login and (2) shells started with the -l
or --login
option.
Type 1 login shells can be detected using the environment variable $SHLVL
. For zsh type 1 login shells $SHLVL
is always equal to 1. This implies that for fizsh type 1 login shells $SHLVL
is always equal to 2. The reason for this is that /usr/bin/fizsh
is a zsh script, in which $SHLVL
is 1. /usr/bin/fizsh
makes sure fizsh can be started with another call to zsh
. This additional call to zsh
increases $SHLVL
to 2.
Type 2 login shells can be detected by exporting an additional environment variable, e.g. $_fizsh_F_LOGIN_OPTION_SET
before fizsh is started in /usr/bin/fizsh
. After fizsh has started this exported variable could copied to a local (i.e. unexported) version of the environment variable, e.g. $_fizsh_F_LOCAL_LOGIN_OPTION_SET
. The original exported variable could subsequently be unset, so that it does not exist, when one more subshell is started.
Depending on the values of the environment variables $SHLVL
, $_fizsh_F_LOGIN_OPTION_SET
, zsh could be called with or without the -l
flag in the script /usr/bin/fiszh
.
Depending on the values of the environment variables $SHLVL
, $_fizsh_F_LOCAL_LOGIN_OPTION_SET
, $0
could be set to -fizsh
or fizsh
by /etc/fizsh/fizshrc
.
In the next version of fizsh I intend to implement the treatment of loginshells as outlined above.
http://www.zsh.org/mla/workers/2007/msg00270.html and subsequent reactions provide interesting information as well.
fizsh's man page should probably mention that things like ssh -t someserver "cd $(pwd) && ARGV0=-\$0 exec \$0"
do not work as described there.
Closing this issue (see the above commits).
PS: The original issue of fizsh not being able to find its path, is IMO misconfiguration problem not specifically related to fizsh.
If Pacman had done the installation, the fizsh script should have been installed in /usr/bin
. This would have prevented the problem. /usr/local/bin
is the responsability of the local administrator. If he decides to install fizsh there, he should make sure that /usr/local/bin
is available when fizsh is started as a login shell. This may for example be achieved by having zprofile
or zlogin
add /usr/local/bin
to the $path variable.
On OSX the issue still persists. Due to security reasons, on OSX 10.11 /usr/bin is protected by SIP (Security Integrity Protection) http://arstechnica.com/apple/2015/09/os-x-10-11-el-capitan-the-ars-technica-review/8/
Installing 1.0.8 can be done by brew install fizsh
and will place bin aliases into /usr/local
fibrics-Mac-Pro% fizsh
welcome to fizsh, the friendly interactive zshell
type man fizsh for instructions on how to use fizsh
fibric@fibrics-Mac-Pro ~>
But when changing my default shell from zsh to fizsh then I see this:
Last login: Sat Oct 3 08:32:55 on ttys001
_fizsh: Make sure that fizsh is installed correctly and that your path is set accordingly
[Process completed]
At the point of [Process completed] the terminal window is dead.
Strange... This error message occurs when the command type fizsh
cannot find the fizsh binary. Not finding the fizsh binary causes your seemingly dead terminal window. Usually this happens when the directory of the fizsh binary is not part of $path. Therefore, after you arrive at the seemingly dead terminal window, can you report the output of type fizsh
and echo $path
?
I do not have OS X
and brew
here. So I cannot test the issue myself.
You might want to check if the problem is related to brew install
. To find out, just install fizsh manually:
mkdir ./fizsh_sources
cd ./fizsh_sources
git clone https://github.com/zsh-users/fizsh.git
cd fizsh
./configure \
--prefix=/usr/local \
--includedir=/usr/local/include \
--datadir=/usr/local/share \
--bindir=/usr/local/bin \
--libexecdir=/usr/local/lib/fizsh \
--localstatedir=/var/local \
--sysconfdir=/etc/local
make
sudo make install
chsh -s /usr/local/bin/fizsh
su $USER
If this does work, I would expect the problem to be caused by brew install
.
Best wishes,
Guido
Manual installation makes no difference.
Could you report the output of type fizsh
and echo $path
?
And could you report the ouput of the manal installation process as well?
It appears, that the path ist set only to /usr/bin
and /bin
and type fizsh
says fizsh not found
. Also fizsh
sources none of the following: /etc/zprofile
, /etc/zshrc
, ~/.zlogin
, ~/.zprofile
– But /etc/zshenv
is sourced, so the path can be set there and it works, without messing with /usr/local/bin/fizsh
. But maybe there is still a better solution...
Thank you for reporting this.
I have read some posts on the OSX-specific way of setting the system-wide path (e.g. https://serverfault.com/questions/16355/how-to-set-global-path-on-os-x). Directories to be included in it should be listed in the file /etc/paths
.
So, local administrators who allow executables in /usr/local/bin/
should add the entry /usr/local/bin/
to the file /etc/paths
. This should be done BEFORE any executable in /usr/local/bin/
is executed.
Changing PATH
in /etc/zshenv
may technically work as well. The same may apply to changing PATH
in /etc/launchd.conf
. However, if I were on OSX I would rather create the system-wide path correctly using /etc/paths
.
It would not hurt to add an extra configuration file called ~/.fprofile
or ~/.zshenv
. This file would be sourced immediately after fizsh
is started. I might add such a file in the next fizsh
release.
ADDED LATER: On second thought: it would hurt. Fizsh is meant to be a friendly shell, and additional configuration files would make fizsh less friendly.
I would like to note, that I added /usr/local/bin
to /etc/paths
(and /etc/launchd.conf
and /etc/paths.d/
) without success. I tried a lot of other stuff too. In the end, using /etc/zshenv
was the only feasible workaround.
I have access to an OSX machine (10.8.5). On this machine there is a file called /etc/zshenv
. It contains:
$ cat /etc/zshenv
...
if [ -x /usr/libexec/path_helper ]; then
eval /usr/libexec/path_helper -s
fi
This path_helper
program sets the path using the contents of /etc/paths
. In my case this seems to work properly.
On OSX 10.11 /etc/zshenv
does not exist anymore and has to be created with this content.
OK, now I understand.
Can you set the path in ~/.zshenv
? Or is that not working either?
Does the path_helper
binary still exist in OSX 10.11?
Yes! I can set the path in ~/.zshenv
and path_helper
still exists and works as advertised.
Thank you, it is good to know this!
The code commited to prevent this issue is https://github.com/zsh-users/fizsh/commit/9a128f3239bd72b52e97281a3377e17b011fd8b6.
On second thought: Since this issue has now been solved in a relatively simple way, I will refrain from adding extra configuration files like /etc/fizsh/fizshenv
and ~/.fizsh/.fizshenv
. Fizsh is meant to be a friendly shell. Therefore, I will keep the number of configuration files as small as possible.
I can report this does work on 10.11. Only comment is that it would be nice to have fizsh tell the user in the error message to try putting PATH in .zshenv rather than making thr user find this thread :-) (BTW great work in general, Iam really enjoying it.) Oh and also --login seems to no longer be required; or at least seems to be working fine without it via iterm and ssh.
When using fizsh as login shell, PATH is not set and fails:
I solved this by sourcing /etc/zsh/zprofile in /usr/local/bin/fizsh before $(type fizsh), but I am unsure if this is the correct solution. Should zprofile be sourced every time?
I am running current Arch Linux, zsh version 5.0.7, fizsh version 1.0.8.