os.Getenv and os.LookupEnv don't return the value of $HISTFILE, $HISTSIZE, and $SAVEHIST


I’m using zsh, and I’m trying to access these environment variables:

$ echo $HISTFILE
$ echo $HISTSIZE
$ echo $SAVEHIST

But os.LookupEnv returns "", false for all three, and os.Getenv, naturally, returns an empty string:

package main

import (

func main() {
    histfile, found := os.LookupEnv("HISTFILE")
    if found {
    } else {
        fmt.Println("$HISTFILE not found")

    histsize, found := os.LookupEnv("HISTSIZE")
    if found {
    } else {
        fmt.Println("$HISTSIZE not found")

    savehist, found := os.LookupEnv("SAVEHIST")
    if found {
    } else {
        fmt.Println("$SAVEHIST not found")
$ go run main.go
$HISTFILE not found
$HISTSIZE not found
$SAVEHIST not found

Now, if I export these variables in $HOME/.zshrc:

$ grep -iE "histfile|histsize|savehist" $HOME/.zshrc
export HISTFILE="$HOME/.zsh_history"
export HISTSIZE=1000000
export SAVEHIST=1000000

Then it works and correct values are returned:

$ go run hyst.go

When I haven’t explicitly exported these variables, the values of $HISTSIZE and $SAVEHIST are different, but they’re not empty. So why do these functions return empty strings for these variables?


That’s because $HISTFILE, $HISTSIZE, and $SAVEHIST are not, by default, environment variables, but rather simply shell variables set by oh-my-zsh:

## History file configuration
[ -z "$HISTFILE" ] && HISTFILE="$HOME/.zsh_history"
[ "$HISTSIZE" -lt 50000 ] && HISTSIZE=50000
[ "$SAVEHIST" -lt 10000 ] && SAVEHIST=10000

These are the values you see when you use echo before using export in $HOME/.zshrc.

It’s important to make a distinction between environment and shell variables:

  • Environment variables are accessible in child processes, but shell variables are not. You can verify this statement by simply creating a child process:

    $ # Child processes don't inherit shell variables
    $ key=value; sh -c 'echo "key=$key"'
    $ # They do, however, inherit environment variables
    $ export key=value; sh -c 'echo "key=$key"'
  • To be able to access a shell variable in the child process, you can export it, just as you did in $HOME/.zshrc:

    $ key=value; export key; sh -c 'echo "key=$key"'

Now, to see if a specific variable is an environment variable or not, instead of using echo, you can directly check the list of environment variables.

$ env | grep -i "shell"; echo $?

So $SHELL is, in fact, an environment variable. Now for the history variables:

$ env | grep -iE "histfile|histsize|savehist"; echo $?

The exit code is 1, meaning that it failed to find these names in the list of environment variables.

Answered By – Amir Shabani

Answer Checked By – David Goodson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.