How to check for SSH session in shell

There are times when you want to check if you are in a SSH session from your shell. For example, I like to change the shell prompt based on whether it is in a local machine or in a SSH session on another machine.

An easy way to do this is to check if any environment variable related to SSH has been set. For example, I check if the SSH_CLIENT variable is set in my shell. In Fish, this can be done by checking the result of set --query SSH_CLIENT for example.

How to set default shell for Byobu

I like to have Fish as my default shell in Byobu. I add these lines to my ~/.byobu/.tmux.conf:

set -g default-shell   /usr/bin/fish
set -g default-command /usr/bin/fish

Note that Byobu will set the SHELL environment variable to the above path. That is, even if you want to set SHELL to something else in your shell’s init file, that will be overridden by Byobu.

Tried with: Byobu 5.74 and Ubuntu 14.04

How to activate virtualenv in Fish

Problem

The typical method to activate a virtualenv is:

$ source your_env_name/bin/activate

This fails in Fish shell:

source: Error while reading file β€œyour_env_name/bin/activate”

Solution

Thankfully, virtualenv ships with an activation script for Fish. Use that instead:

$ source your_env_name/bin/activate.fish

Tried with: Ubuntu 14.04

Environment variables in Fish

Environment variables can be set just like any other variable in the Fish shell.

  • To export an environment variable to the shell, add it in ~/.config/fish/config.fish:
set -x FOO_ENV_VAR /home/joe/bin/some_foo_dir
  • If this a environment variable with many values, then set it as an array. In Fish, you set an array variable with a space-delimited series of values:
set -x FOO_ENV_VAR /home/joe/bin/some_foo_dir /usr/local/foo_dir

Under Bash, you might have set this same environment variable in ~/.bashrc as:

export FOO_ENV_VAR=/home/joe/bin/some_foo_dir:/usr/local/foo_dir
  • If the environment variable with many values already exists and you want to prepend or append a value to it, the technique is the same. For example, to prepend to PATH:
set -x PATH /home/joe/bin/some_foo_dir $PATH
  • Three special environment variables: PATH, CDPATH and MANPATH are treated differently by Fish. These arrive from the environment to Fish as colon-separated, they are converted to array so we can set them easily as shown above using space-delimiter and then they are sent back to the environment as colon-separated. This logic can be seen in the Fish source code file src/env.cpp here. This is also explained in this issue.

  • The problem now is that there are many other environment variables which need to be colon-delimited, but Fish does not do that. For example, the dynamic linker ld.so that is used to load up DLLs when a binary executes requires LD_LIBRARY_PATH environment variable to be colon-delimited. I got errors when this variable was set using space-delimiters: cannot open shared object file: No such file or directory

  • If you run into any problems with an environment variable that takes a series of values, then check back to see how it is set in traditional shells like Bash. If it is colon-delimited there, then you might need to make it colon-delimited in Fish too. But, do remember to enclose it in double quotes for variable expansion to work correctly. For example:

set -x FOO_ENV_VAR "/home/joe/bin/some_foo_dir:$FOO_ENV_VAR"

Tried with: Fish 2.2 and Ubuntu 14.04

Autojump path repeats in PATH in Fish

Problem

Autojump can be installed and used with Fish shell as described here. However, if you source your Fish config file repeatedly, then the autojump path appears repeated in your PATH environment variable:

$ echo $PATH
/home/joe/.autojump/bin /home/joe/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
$ source ~/.config/fish/config.fish
$ echo $PATH
/home/joe/.autojump/bin /home/joe/.autojump/bin /home/joe/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin

Solution

I have a commit here that fixes this behavior. This pull request hopefully be merged into Autojump and if you get the latest version of Autojump you should no longer face this problem.

Tried with: Autojump 22.2.4, Fish 2.2 and Ubuntu 14.04

How to view man pages in color in Fish

Man pages in color
Man pages in color

When you open a man page you are confronted with a wall of white-on-black text. You may have noticed that man pages have some formatting information. This can be used to render the formatted elements in various colors. This can make reading and searching for information in a man page a pleasant affair.

To render man pages with colors in the Fish shell, add these lines to ~/.config/fish/config.fish:

set -x LESS_TERMCAP_mb (printf "33[01;31m")  
set -x LESS_TERMCAP_md (printf "33[01;31m")  
set -x LESS_TERMCAP_me (printf "33[0m")  
set -x LESS_TERMCAP_se (printf "33[0m")  
set -x LESS_TERMCAP_so (printf "33[01;44;33m")  
set -x LESS_TERMCAP_ue (printf "33[0m")  
set -x LESS_TERMCAP_us (printf "33[01;32m")

Tried with: Fish 2.2b1 and Ubuntu 14.04

Time command in Fish shell

Running the time command in the Bash shell, gives output split across the very familiar real, user and sys sections:

$ time ./do_something

real    0m1.210s
user    0m0.158s
sys 0m0.033s

However, running time in the Fish shell, gives output in a different format:

$ time ./do_something

0.38user 0.08system 0:07.34elapsed 6%CPU (0avgtext+0avgdata 20116maxresident)k
7968inputs+192outputs (89major+25318minor)pagefaults 0swaps

The difference in output is because these two time programs are different. The Bash time is a command internal to that shell. Fish does not have in inbuilt time command, so it runs the binary /usr/bin/time whose output is of the above format.

If you like the simple format of the Bash time command and want it under Fish, use the -p option of the time binary:

$ time -p ./do_something

real 1.81
user 0.17
sys 0.02

If you would like this to be the default output format of time in Fish, then add the below lines to your ~/.config/fish/config.fish file:

function time --description="Time just like in Bash"
    command time --portability $argv
end

Tried with: Time 1.7-24, Fish 2.1.1, Bash 4.3.11 and Ubuntu 14.04

Directory history in the Fish shell

The Fish shell makes it very easy to jump around in your directory history. This is the list of directories that you had changed to using the cd command.

  • Fish supports jumping back to the previous directory, just like in Bash: cd -

  • To view the directory history: dirh You can see your current directory highlighted in color in this list.

  • To move to the next and previous directory in your history, use the nextd and prevd commands.

  • Typing these commands is too much? Not to worry, at an empty Fish prompt, you can cycle to your previous and next directories by just pressing the Alt + Left and Alt + Right keys.

  • Note: The Alt + Left and Alt + Right shortcuts might have been grabbed by your terminal program, like GNOME Terminal. They need to be freed for this to work. I use Terminator, where I disabled these keybindings by right-clicking in the terminal -> Preferences -> Keybindings.

Tried with: Fish 2.2b1, Terminator 0.97-2 and Ubuntu 14.04

How to install Fish

Fish is a modern shell that has user-friendly features like colors and auto-completion and works right out of the box.

Ubuntu already ships Fish, so installing it is easy:

$ sudo apt install fish

The version of Fish that Ubuntu maintains is quite old. Fish is under active development, with lots of new features added regularly. If you want the latest stable version of Fish:

$ sudo apt remove fish
$ sudo add-apt-repository ppa:fish-shell/release-2
$ sudo apt-get update
$ sudo apt install fish

If you want the latest beta version of Fish:

$ sudo apt remove fish
$ sudo add-apt-repository ppa:fish-shell/beta-2
$ sudo apt-get update
$ sudo apt install fish

Tried with: Fish 2.2b1 and Ubuntu 14.04