Execute a script when moving to it's dir? - bash

I'm playing around with virtualenv and pip, but I find it quite restrictive to have to "source bin/activate" each time I come into a virtualenv dir.
So I'd like to automate it. Any ideas of a way to execute a script once we change to it's dir, or a shell features enabling this behavior?

Maybe you're looking for something like this in your .bash_profile::
has_virtualenv() {
if [ -e .venv ]; then
workon `cat .venv`
fi
}
venv_cd () {
cd "$#" && has_virtualenv
}
alias cd="venv_cd"
It replaces default cd command with a script which 1) does the actual cd, 2) checks for .venv file inside new directory, 3) if it's found, assumes that the file contains virtual environment name and executes workon `cat .venv`.
workon command is a replacement for plain source bin/activate; it's provided by virtualenvwrapper and has some niceties like postactivate hook. See project page for more details.
That piece of code above I found via post by Justin Lilly. See also tips in virtualenvwrapper's docs for some other cool stuff.

Related

how can i make my bash script (.sh) to run locally as a bash command? [duplicate]

If I have a basic Python script, with it's hashbang and what-not in place, so that from the terminal on Linux I can run
/path/to/file/MyScript [args]
without executing through the interpreter or any file extensions, and it will execute the program.
So would I install this script so that I can type simply
MyScript [args]
anywhere in the system and it will run? Can this be implemented for all users on the system, or must it be redone for each one? Do I simply place the script in a specific directory, or are other things necessary?
The best place to put things like this is /usr/local/bin.
This is the normal place to put custom installed binaries, and should be early in your PATH.
Simply copy the script there (probably using sudo), and it should work for any user.
Walkthrough of making a python script available anywhere:
Make a python script:
cd /home/el/bin
touch stuff.py
chmod +x stuff.py
Find out where your python is:
which python
/usr/bin/python
Put this code in there:
#!/usr/bin/python
print "hi"
Run in it the same directory:
python stuff.py
Go up a directory and it's not available:
cd ..
stuff.py
-bash: stuff.py: command not found
Not found! It's as we expect, add the file path of the python file to the $PATH
vi ~/.bashrc
Add the file:
export PATH=$PATH:/home/el/bin
Save it out, re apply the .bashrc, and retry
source ~/.bashrc
Try again:
cd /home/el
stuff.py
Prints:
hi
The trick is that the bash shell knows the language of the file via the shebang.
you can also use setuptools (https://pypi.org/project/setuptools/)
your script will be:
def hi():
print("hi")
(suppose the file name is hello.py)
also add __init__.py file next to your script (with nothing in it).
add setup.py script, with the content:
#!/usr/bin/env python3
import setuptools
install_requires = [
'WHATEVER PACKAGES YOU NEED GOES HERE'
]
setuptools.setup(
name="some_utils",
version="1.1",
packages=setuptools.find_packages(),
install_requires=install_requires,
entry_points={
'console_scripts': [
'cool_script = hello:hi',
],
},
include_package_data=True,
)
you can now run python setup.py develop in this folder
then from anywhere, run cool_script and your script will run.
Just create ~/bin and put export PATH=$PATH:$HOME/bin in your bashrc/profile. Don't mess with the system, it will bite you back, trust me.
Few more things (relevant to the question but not part of the answer):
The other way export PATH=$HOME/bin:$PATH is NOT safe, for bash will will look into your ~/bin folder for executables, and if their name matches with other executables in your original $PATH you will be surprised by unexpected/non working command execution.
Don't forget to chmod+x when you save your script in ~/bin.
Be aware of what you are putting in your ~/bin folder, if you are just testing something or working on unfinished script, its always better to use ./$SCRIPT_NAME from your CWD to execute the script than putting it under ~/bin.
The quick answer is to symlink your script to any directory included in your system $PATH.
The long answer is described below with a walk through example, (this is what I normally do):
a) Create the script e.g. $HOME/Desktop/myscript.py:
#!/usr/bin/python
print("Hello Pythonista!")
b) Change the permission of the script file to make it executable:
$ chmod +x myscript.py
c) Add a customized directory to the $PATH (see why in the notes below) to use it for the user's scripts:
$ export PATH="$PATH:$HOME/bin"
d) Create a symbolic link to the script as follows:
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
Notice that hello (can be anything) is the name of the command that you will use to invoke your script.
Note:
i) The reason to use $HOME/bin instead of the /usr/local/bin is to separate the local scripts from those of other users (if you wish to) and other installed stuff.
ii) To create a symlink you should use the complete correct path, i.e.
$HOME/bin GOOD ~/bin NO GOOD!
Here is a complete example:
$ pwd
~/Desktop
$ cat > myscript.py << EOF
> #!/usr/bin/python
> print("Hello Pythonista!")
> EOF
$ export PATH="$PATH:$HOME/bin"
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
$ chmod +x myscript.py
$ hello
Hello Pythonista!
Just create symbolic link to your script in /usr/local/bin/:
sudo ln -s /path/to/your/script.py /usr/local/bin/script
Putting the script somewhere in the PATH (like /usr/local/bin) is a good solution, but this forces all the users of your system to use/see your script.
Adding an alias in /etc/profile could be a way to do what you want allowing the users of your system to undo this using the unalias command. The line to be added would be:
alias MyScript=/path/to/file/MyScript
i find a simple alias in my ~/.bash_profile or ~/.zshrc is the easiest:
alias myscript="python path/to/my/script.py"
Type echo $PATH in a shell. Those are the directories searched when you type command, so put it in one of those.
Edit: Apparently don't use /usr/bin, use /usr/local/bin
Acording to FHS, the /usr/local/bin/ is the good place for custom scripts.
I prefer to make them 755 root:root, after copying them there.

learning bash: Can't activate environment

I've set up Ubuntu in Windows 10 and am in my home directory:
/mnt/c/Users/Me$
I want to end up in my environment directory and have it activated.
I created a file called goenv.sh in this directory and it contains:
#!/bin/bash
source environments/my_env/bin/activate
I changed the permissions of goenv.sh then tried to run it with:
./goenv.sh
...but nothing happens. What am I missing?
The script ./goenv.sh runs in a sub shell. That means that all environment changes are local to that sub shell but have no impact on the calling shell (the shell where you started it).
You need to define a function in your .bashrc to achieve that:
function goenv() {
cd environments
source my_env/bin/activate
}
Anyhow, that looks like a Python virtualenv. I recommend to install virtualenvwrapper which comes with handy shell functions to work with virtualenvs. Having it installed, you just run:
workon my_env
It works now. I changed the script shown in my question to:
#!/bin/bash
cd environments
source ./my_env/bin/activate

Activating a VirtualEnv using a shell script doesn't seem to work

I tried activating a VirtualEnv through a shell script like the one below but it doesn't seem to work,
#!/bin/sh
source ~/.virtualenvs/pinax-env/bin/activate
I get the following error
$ sh virtualenv_activate.sh
virtualenv_activate.sh: 2: source: not found
but if I enter the same command on terminal it seems to work
$ source ~/.virtualenvs/pinax-env/bin/activate
(pinax-env)gautam#Aspirebuntu:$
So I changed the shell script to
#!/bin/bash
source ~/.virtualenvs/pinax-env/bin/activate
as suggested and used
$ bash virtualenv_activate.sh
gautam#Aspirebuntu:$
to run the script .
That doesn't throw an error but neither does that activate the virtual env
So any suggestion on how to solve this problem ?
PS : I am using Ubuntu 11.04
TLDR
Must run the .sh script with source instead of the script solely
source your-script.sh
and not
your-script.sh
Details
sh is not the same as bash (although some systems simply link sh to bash, so running sh actually runs bash). You can think of sh as a watered down version of bash. One thing that bash has that sh does not is the "source" command. This is why you're getting that error... source runs fine in your bash shell. But when you start your script using sh, you run the script in an shell in a subprocess. Since that script is running in sh, "source" is not found.
The solution is to run the script in bash instead. Change the first line to...
#!/bin/bash
Then run with...
./virtualenv_activate.sh
...or...
/bin/bash virtualenv_activate.sh
Edit:
If you want the activation of the virtualenv to change the shell that you call the script from, you need to use the "source" or "dot operator". This ensures that the script is run in the current shell (and therefore changes the current environment)...
source virtualenv_activate.sh
...or...
. virtualenv_activate.sh
As a side note, this is why virtualenv always says you need to use "source" to run it's activate script.
source is an builtin shell command in bash, and is not available in sh. If i remember correctly then virtual env does a lot of path and environment variables manipulation. Even running it as bash virtualenv_blah.sh wont work since this will simply create the environment inside the sub-shell.
Try . virtualenv_activate.sh or source virtualenv_activate.sh this basically gets the script to run in your current environment and all the environment variables modified by virtualenv's activate will be available.
HTH.
Edit: Here is a link that might help - http://ss64.com/bash/period.html
On Mac OS X your proposals seems not working.
I have done it this way. I'am not very happy with solution, but share it anyway here and hope, that maybe somebody will suggest the better one:
In activate.sh I have
echo 'source /Users/andi/.virtualenvs/data_science/bin/activate'
I give execution permissions by: chmod +x activate.sh
And I execute this way:
`./activate.sh`
Notice that there are paranthesis in form of ASCII code 96 = ` ( Grave accent )
For me best way work as below.
Create start-my-py-software.sh and pest below code
#!/bin/bash
source "/home/snippetbucket.com/source/AIML-Server-CloudPlatform/bin/activate"
python --version
python /home/snippetbucket.com/source/AIML-Server-CloudPlatform/main.py
Give file permission to run like below.
chmod +x start-my-py-software.sh
Now run like below
.start-my-py-software.sh
and that's it, start my python based server or any other code.
ubuntu #18.0
In my case, Ubuntu 16.04, the methods above didn't worked well or it needs much works.
I just made a link of 'activate' script file and copy it to home folder(or $PATH accessible folder) and renamed it simple one like 'actai'.
Then in a terminal, just call 'source actai'. It worked!

How can I execute a python script directly (without prefixing by the python command) from bash?

I am just starting to use terminal for my programming needs. In a lot of Django tutorials I see people say, for example, I should type this in terminal:
manage.py runserver
However when I do this it says:
bash: manage.py: command not found
I get it to work when I do: python manage.py runserver, however I would like to understand why this works and the other method doesn't. I guess these are some very basic things but I thought I'd ask here.
It is because your manage.py is not an executable script.
First put this line at the top of manage.py (assuming your python is in /usr/bin/python):
#!/usr/bin/python
Then make your script executable:
chmod +x manage.py
Then try to execute your script ./manage.py runserver.
Read this link for more info: http://effbot.org/pyfaq/how-do-i-make-a-python-script-executable-on-unix.htm
bash(1) will search your PATH environment variable to find programs to execute. PATH does not normally contain your "current working directory" (.) because that opens people up to trivial security problems:
cd /home/unsavory_character/
ls
If unsavory_character places an executable in /home/unsavory_character/ls that adds his or her ssh(1) key to your ~/.ssh/authorized_keys file, you'd be in for a surprise -- he or she could log in as you without a password.
So systems these days don't add the current working directory to the PATH, because it is too unsafe.
The workaround:
./manage.py runserver
Of course, that assumes your current working directory is whichever directory contains the manage.py script. That might be a safe assumption. If you'd like to be able to execute it from anywhere in the filesystem, you can add the directory to your PATH by editing your ~/.profile or ~/.bash_profile or ~/.bashrc file. (If one of them already exists, pick that one. I seem to recall others with PATH problems on OS X found one or the the other file worked well, and the other one never got executed.)
(In my case, I have a bunch of self-written utilities in ~/bin/, but yours might be elsewhere. Change the paths as appropriate.)
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
manage.py needs to be executable. Try: chmod +x manage.py
I've cooked together a small "script" to automate this: (just copy whole text, and paste inside your active terminal.)
tee -a ~/.profile <<EOF
if [ -d "/Library/Python/2.6/site-packages/django/bin" ] ; then
PATH=/Library/Python/2.6/site-packages/django/bin:$PATH
fi
EOF
Doesn't django-admin.py do the same? I think so, because I can find manage.py inside my ../bin folder. And stated at the official documentation, they do the same. So I believe ;)
Also, have you obtained Django via easy_install? My script expect that you are using Snow Leopard with the system version (Python 2.6).

Getting a 'source: not found' error when using source in a bash script

I'm trying to write (what I thought would be) a simple bash script that will:
run virtualenv to create a new environment at $1
activate the virtual environment
do some more stuff (install django, add django-admin.py to the virtualenv's path, etc.)
Step 1 works quite well, but I can't seem to activate the virtualenv. For those not familiar with virtualenv, it creates an activate file that activates the virtual environment. From the CLI, you run it using source
source $env_name/bin/activate
Where $env_name, obviously, is the name of the dir that the virtual env is installed in.
In my script, after creating the virtual environment, I store the path to the activate script like this:
activate="`pwd`/$ENV_NAME/bin/activate"
But when I call source "$activate", I get this:
/home/clawlor/bin/scripts/djangoenv: 20: source: not found
I know that $activate contains the correct path to the activate script, in fact I even test that a file is there before I call source. But source itself can't seem to find it. I've also tried running all of the steps manually in the CLI, where everything works fine.
In my research I found this script, which is similar to what I want but is also doing a lot of other things that I don't need, like storing all of the virtual environments in a ~/.virtualenv directory (or whatever is in $WORKON_HOME). But it seems to me that he is creating the path to activate, and calling source "$activate" in basically the same way I am.
Here is the script in its entirety:
#!/bin/sh
PYTHON_PATH=~/bin/python-2.6.1/bin/python
if [ $# = 1 ]
then
ENV_NAME="$1"
virtualenv -p $PYTHON_PATH --no-site-packages $ENV_NAME
activate="`pwd`/$ENV_NAME/bin/activate"
if [ ! -f "$activate" ]
then
echo "ERROR: activate not found at $activate"
return 1
fi
source "$activate"
else
echo 'Usage: djangoenv ENV_NAME'
fi
DISCLAIMER: My bash script-fu is pretty weak. I'm fairly comfortable at the CLI, but there may well be some extremely stupid reason this isn't working.
If you're writing a bash script, call it by name:
#!/bin/bash
/bin/sh is not guaranteed to be bash. This caused a ton of broken scripts in Ubuntu some years ago (IIRC).
The source builtin works just fine in bash; but you might as well just use dot like Norman suggested.
In the POSIX standard, which /bin/sh is supposed to respect, the command is . (a single dot), not source. The source command is a csh-ism that has been pulled into bash.
Try
. $env_name/bin/activate
Or if you must have non-POSIX bash-isms in your code, use #!/bin/bash.
In Ubuntu if you execute the script with sh scriptname.sh you get this problem.
Try executing the script with ./scriptname.sh instead.
best to add the full path of the file you intend to source.
eg
source ./.env instead of source .env
or source /var/www/html/site1/.env

Resources