2

I am launching an URxvt terminal from a startup script. When the terminal launches, I would like to work in a specific directory with a specific Python virtualenv loaded. These are the commands that accomplish this in an already running terminal:

$ cd myproject $ workon myvirtualenv 

Now, what is the command needed to launch this terminal? This is what I tried:

# called from startup script: /usr/bin/urxvt -e bash -ic 'cd myproject; workon myvirtualenv' 

This works, but that is hardly noticable because the terminal exits as soon as the two commands complete, which is almost immediately. I can prevent this from happening by calling bash again, like so:

# called from startup script: /usr/bin/urxvt -e bash -ic 'cd myproject; workon myvirtualenv; exec bash -i' 

But now the virtualenv isn't activated anymore in the second instance of bash, although the effect of the cd command does persist.

How can I spawn an URxvt terminal with an activated virtualenv?

2 Answers 2

2

workon is a function (not a separate executable) for a reason: its job is to set something in the current shell. I don't use the tool and I don't know the details. It's irrelevant if it sets variables, functions, aliases, traps, shell options or whatever. The important thing is when you run exec bash -i, a new bash starts and at least some of these customizations are not preserved.

Solution: make this exact bash -i run workon myvirtualenv for itself.

The idea is to run exec bash -i in an environment where the existence and the content of some environment variable will tell the shell to run workon …. Add this to your ~/.bashrc:

[ -n "$AUTOWORKON" ] && workon "$AUTOWORKON" 

It must be executed after workon is defined. The very end of your ~/.bashrc is most likely the best place.

Run urxvt this way:

/usr/bin/urxvt -e sh -c 'cd myproject; AUTOWORKON=myvirtualenv exec bash -i' 

Notes:

  • The first shell doesn't need to be bash; it doesn't need to be interactive. I used sh -c …, it should be fine.

  • AUTOWORKON will be in the environment of bash, so if you run yet another bash that reads ~/.bashrc then it will also execute workon … from our line in the file. I cannot tell if you want this. If not, unset AUTOWORKON in ~/.bashrc after using its value. Change our line to:

    [ -n "$AUTOWORKON" ] && { workon "$AUTOWORKON"; unset AUTOWORKON; } 

    Another possibility is to remove the export property from the variable: export -n AUTOWORKON.

  • I arbitrarily chose AUTOWORKON as the name for the variable. If it collides with anything in your current setup then use another name.

3
  • workon is part of virtualenvwrapper.readthedocs.io and is indeed a shell function. Is there no way to run a specified shell function on invocation of bash without having to customize my .bashrc? Commented Oct 20, 2020 at 12:52
  • @hedgie There is --rcfile (see man 1 bash), so you can source something instead of ~/.bashrc. I guess the chosen file can source ~/.bashrc and then run workon …. I haven't tested this. Commented Oct 20, 2020 at 13:00
  • Interesting! I'll look into this! Commented Oct 20, 2020 at 14:24
0

I found another option. Big thanks to Kamil for putting me on the right path! The following command will spawn a new terminal that does not exit immediately:

urxvt -e bash --rcfile <(echo '. /etc/bash.bashrc; . ~/.bashrc; cd myproject; workon myvirtualenv') 

Explanation:

  • urxvt: Launches URxvt.
  • -e bash --rcfile ...: Upon launch, execute bash with the --rcfile argument. This will source the filename that follows instead of the default .bashrc file.
  • <(echo ...): special bash syntax for Process Substitution. This replaces the command inside the parentheses by a filename like /dev/fd/62 which is a file descriptor containing the output of the command. You can use this to give filenames to commands that don't allow standard input, such as bash --rcfile
  • '. /etc/bash.bashrc; . ~/.bashrc; cd myproject; workon myvirtualenv': The contents of the on-the-fly generated rcfile. This contains the actual commands that happen before the shell will accept regular user input.

Since this command uses syntax only available in bash, it can only be run from the bash shell. The following slightly more complicated command works in any shell:

urxvt -e bash -c "exec bash --rcfile <(echo '. /etc/bash.bashrc; . ~/.bashrc; cd myproject; workon myvirtualenv')" 

This would be more suitable for a typical startup command, for example in ~/.xsessionrc or ~/.xinitrc.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.