Should I put an alias in .bashrc or .profile?

Solution 1:

TL;DR: Based on the description you've given, it can all go in ~/.bashrc, even though you would usually not want to put environment variables there. There are some other changes you may want to make: exporting the variables is probably unnecessary, and their expansions are best quoted.

As with Bash aliases in general, you can put your gc alias in ~/.bashrc or in ~/.bash_aliases but it should not go in .profile. If the variables are only ever needed in shells where the aliases (which expand to commands that use them) are available, then it is actually fine to put them in the same place as the aliases.

In that case, I'd suggest putting the aliases and variables in ~/.bashrc, since while it is possible to put any commands in ~/.bash_aliases, it's unusual to put anything other than alias definitions there, and doing so may confuse future readers of your code (perhaps including yourself) and motivate them to wonder if they are looking at a mistake. Of course, you could put the aliases in ~/.bash_aliases and the associated variables in ~/.bashrc, but I think that would be much more confusing.

Normally one should not put environment variables in ~/.bashrc. Most of the time, a user-specific environment variable should either go in ~/.pam_environment, which uses its own special syntax, or ~/.profile, which contains shell commands as ~/.bashrc does. (See also these comments.) One of the reasons for this is that those methods cause the environment variable to be available in most of the situations where it may be needed, which putting it in ~/.bashrc fails to achieve; one of the reasons for that is that ~/.bashrc is only used by bash, and when you log in graphically, that's not bash. But when you only need your variables when the aliases that use them are also available, this doesn't apply.

Nonetheless, I suspect that this is actually not an exception. But instead of needing to go elsewhere than .bashrc, it looks like those variables don't need to be environment variables. This is to say that it looks like you don't have to export them, but could instead simply write:

ZONE="us-eastern1-c"
INSTANCE_NAME="myInstance"

This is about the distinction between a shell variable and an environment variable. In Bourne-style shells like Bash, all environment variables are shell variables, but the only shell variables that are environment variables are those that the shell inherited from its parent process's environment or that have been exported with the export builtin.

If programs you run need to inherit ZONE and INSTANCE_NAME into their environments, they you do indeed need to export them as environment variables. And if you need that even in contexts where ~/.bashrc is not sourced (e.g., running scripts), then it is not sufficient to put those environment variables in ~/.bashrc.

Otherwise, they can just be shell variables, as shown above. The shell will still find them and perform parameter expansion on them, in commands generated by expanding the gc alias.


Whatever you do, I recommend that you modify your alias definition to double-quote those variables when it performs parameter expansion. One way to do that is to define the alias like this:

alias gc='gcloud compute ssh --zone="$ZONE" "jupyter@$INSTANCE_NAME" -- -L 8080:localhost:8080'

Given the their initial values you've shown, that only makes a difference when $IFS has an unusual value, since they contain neither whitespace nor any globbing characters like *. But it is bad practice to perform unquoted parameter expansion unless you actually intend for word splitting or globbing to occur.

More importantly, if those variables are reassigned, the new values are used when the command the alias expands to is run. The alias will still expand to the same command (the command it expands to doesn't depend on those variables' values), but the subsequent parameter expansions carried out on $ZONE and $INSTANCE_NAME will expand them to the new values. Quoting those expansions with double quotes guards against wrong behavior when variables deliberately contain whitespace (or anything in $IFS) or any of *, ? and [. But you should do it even if you believe or know they should never take on such values, so if they are given such a value by accident, you get comprehensible error messages rather than bizarre and unexpected behavior.

If you don't actually want those variables to exist at all, and you are only using them to make the definition of gc more self-documenting, then you can define gc as a function (in ~/.bashrc) instead of an alias and make them local variables:

gc() {
    local ZONE="us-eastern1-c"
    local INSTANCE_NAME="myInstance"
    gcloud compute ssh --zone="$ZONE" "jupyter@$INSTANCE_NAME" -- -L 8080:localhost:8080
}