Bash – Forward aliases to child process

aliasbashzsh

I have some aliases which are defined in /etc/zprofile (or /etc/profile for bash). Also $PATH gets manipulated there.

I want to start an interactive shell from a shell which avoids the $PATH manipulation. I do this by starting it with the -f option. Yet, the aliases which are defined in the parent shell are useful and I'd like to forward them to the child process.

Copy and pasting the aliases which are defined by /etc/zprofile once into a text file and sourcing it every time I start another shell is not what I'm looking for as the definitions in /etc/zprofile get maintained and may change over time.

Do you have a recommendation how to forward aliases to the second shell?

(My main interest are zsh solutions, but I'm curious about bash solutions as well)

This is how the situation looks to me

# log in with ssh
shell1 > echo "here aliases are the way I want them to be"
shell1 > VARIABLE1=value1 VARIABLE2=value2 PATH=some_paths zsh
shell2 > echo "/etc/zprofile prepended something to PATH, which I don't like"
shell2 > echo "aliases are good"
shell2 > exit
shell1 > VARIABLE1=value1 VARIABLE2=value2 PATH=some_paths zsh -f
shell2 > echo "/etc/zprofile did not prepend something to PATH. This is good!"
shell2 > echo "but all aliases from shell 1 are \"forgotten\""
shell2 > exit

Continuing to provide information; the things in /etc are more involved than I initially thought:
/etc/zprofile contains the following, which I traced down to be what defines my aliases and $PATH

_src_etc_profile()
{
    #  Make /etc/profile happier, and have possible ~/.zshenv options like
    # NOMATCH ignored.
    #
    emulate -L ksh

    # source profile
    if [ -f /etc/profile ]; then
        source /etc/profile
    fi
}
_src_etc_profile

unset -f _src_etc_profile

but I missed that /etc/zshrc contains

_src_etc_profile_d()
{
    #  Make the *.sh things happier, and have possible ~/.zshenv options like
    # NOMATCH ignored.
    emulate -L ksh


    # from bashrc, with zsh fixes
    if [[ ! -o login ]]; then # We're not a login shell
        for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . $i
        fi
        done
        unset i
    fi
}
_src_etc_profile_d

unset -f _src_etc_profile_d

so it's not only zprofile which goes through /etc/profile.d but also zshrc. One of the files in /etc/profile.d does then (with comments added by me for how it goes on)

if [ -n "$SHLVL" ]; then
    if [ $SHLVL = 1 ]; then
            source /some/group/path/profile
            # calls "source /some/group/path/env"
            # -> see else branch
    else
            source /some/group/path/env
            # calls "source /some/group/path/${SHELL}rc"
            # which then calls
            # "source /my/group/path/group_zshrc"
    fi
else
    echo 'No $SHLVL available, assuming login shell.'
    source /some/group/path/profile
fi

and ultimately /my/group/path/group_zshrc calls a python program which writes a temporary file in which aliasses and environment variables are defined / manipulated, which is then sourced in the end.

Best Answer

You shouldn't define aliases in /etc/zprofile or ~/.zprofile. These files is only loaded in login shells (“shells” meaning zsh of course). The proper place to define aliases is in /etc/zshrc or ~/.zshrc, which is read by all interactive shells.

To run zsh without loading /etc/zprofile, just run zsh with no option. The option -f tells zsh not to read configuration files at all, but since you want to read your alias definitions, that's not the right option. Since /etc/zprofile is only read by a login shell, just don't pass the -l option (and don't set a zeroth argument that begins with a dash).

Zsh has no option or environment variable to read one extra file on startup. If you want to prepare for that, you can add eval $ZSH_EXTRA_STARTUP_CODE to your .zshrc.

You can set the ZDOTDIR environment variable to make it read all of its user configuration files from a different directory, e.g. ZDOTDIR=/tmp/foo zsh reads /etc/zshenv, /tmp/foo/.zshenv, /etc/zshrc and /tmp/foo/zshrc. So to export aliases from the current instance to a child instance, you can run something like

tmp=$(mktemp -d)
alias -L >$tmp/.zshenv
echo ". ~/.zshenv; unset ZDOTDIR; rm -r ${(q)tmp}" >>$tmp/.zshenv
zsh
Related Question