Activating virtualenv in Bash script not working - bash

Writing a script to automate my flask environment setup.
if [[ -z $1 ]];
then
echo "usage: flaskup <dirname> <template dir>";
exit
else
virtualenv $1 &&
cd ./$1 &&
source bin/activate &&
bin/pip install flask &&
mkdir ./app &&
mkdir ./app/static &&
mkdir ./app/templates &&
exit;
fi
I'm expecting this to leave me in the directory it created, with the virtual environment activated, however it leaves me in the same directory I ran the script from. What can I do to make the script exit with the shell in the activated virtual environment?

If you run the script in its own shell (run it as /path/to/script or script if it lives in your $PATH) then you can't get what you want. The shell that runs the script is a different shell then the one you ran it from and it cannot change the status of the parent shell. The closest you could do would be to have the script echo the path as output and run it as cd "$(/path/to/script)" or similar.
Alternatively, if you run the script as . /path/to/script (or similar) then you are running it with your current shell and any directory changes it makes will be happening in your current shell and not a sub-shell.

Related

Executing single function from Shell script in Windows GitBash closes shell unexpectedly

I have recently installed Git For Windows version 2.19.1.windows.1 in my Windows 64Bit (both Windows 7 and 10, in two systems).
Now I have created below script to do some regular tasks easily w/o writing every instruction separately:
#!/bin/bash
## Contains functions and methods that can be executed inside Vagrant SSH Session
export SCRIPT_PATH="$(cd "$(dirname "$0")"; pwd -P)"
export PROJECT_ROOT_PATH="/var/www" PROJECT_ROOT_DIR="/var/www" ROOT_FOLDER="/var/www"
function fcc() {
echo "########## Frontend Cache clear begins #############"
[[ "$PWD" =~ "frontend/app" ]] && cd frontend/app
rm -rf webroot/cache_js && rm -rf webroot/cache_css
mkdir -m 777 webroot/cache_js && mkdir -m 777 webroot/cache_css
Console/cake AssetCompress.AssetCompress build -f
cat /dev/null > ~/.bash_history && history -wc && history -cw && exit
cd /var/www
echo "########## Frontend Cache clear ends #############"
keep_shell_open
}
function bocc() {
...
}
function bcc() {
...
}
function succ() {
...
}
function keep_shell_open() { exec $SHELL; };
Now when goto script's directory thro' Gitbash terminal & I register the script as below it unexpectedly opens the C:\Program Files\Git\usr\bin directory of GitBash:
. ./VagrantGuestScript.sh
And then when I execute the "fcc" function of this script, it only executes first 2 or 3 lines and then closes the terminal.
Can anyone explain why it opens Gitbash's bin path when trying to register the script & why it closes the terminal after executing only 2/3 lines of the function "fcc" ?

How to execute a script from within another script?

I'm having trouble executing some files under a BASH script.
What I want is, when running the SCRIPT.SH, to check if the directory from which it's running is the right one. Which in this case it's /ROOT/OPENSOURCE . If it's not, then it asks if the user wants to move the directory into the correct place. Doing this by another script /OPENSOURCE/MODULES/MOVE.SH.
I have this variable to get the script launching dir:
spath="$( cd "$( dirname $0 )" && pwd )"
Now since the script will not be installed on the right directory, I need to run MOVE.SH which is in the MODULES directory inside OPENSOURCE. I can't get this done.
Code:
# check if script is on correct directory
if [ "$rpath" = "$spath" ]; then
Colors;
echo ${RedF}[x] [WAIT]${YellowF} Checking directory: ${Reset};
sleep 1
echo ${BlueF}[*] [Directory]:${GreenF} OK ${Reset};
else
Colors;
echo ${RedF}[x] [WAIT]${YellowF} Checking directory: ${Reset};
sleep 1
echo ${BlueF}[*] [Directory]:${RedF} FAILED: This may cause a script malfunction ${Reset};
read -p "[!] Move script directory to right directory {y|n}:" pass
if test "$pass" = "y"
then
echo ${BlueF}[*] [Directory]: ${GreenF}Ok. Moving script to new directory${Reset};
sleep 1
---- COMMAND WILL BE HERE ----
else
echo ${BlueF}[*] [Directory]: ${YellowF}Ok not moving ${Reset};
fi
fi
How can I do it ?
I'm not sure I 100% understand the question, but I think you might just be looking for the mysterious "." command, which will run another script.
Example:
test.sh:
#!/bin/bash
echo running other script $1
. $1
echo done
test2.sh:
#!/bin/bash
echo I am the other script
Run it:
> ./test.sh test2.sh
running other script test2.sh
I am the other script
done

Cannot Create Directories On Ubuntu With Bash Shell Script

I'm trying to run this bash shell script to create directories for vim syntax highlighting on Ubuntu 13.04 (via Vagrant 1.4.1 on Windows 7).
#!/usr/bin/env bash
basevim="$HOME/.vim"
ftdetect="${basevim}/ftdetect"
indent="${basevim}/indent"
syntax="${basevim}/syntax"
echo "Setting up VIM for syntax highlighting"
#Create directories for vim syntax highlighting
if [ ! -d "$basevim" ]; then
echo "Adding VIM syntax highlighting dirs"
mkdir "$basevim"
mkdir "$ftdetect"
mkdir "$indent"
mkdir "$syntax"
else
if [ ! -d "$ftdetect" ]; then
mkdir "$ftdetect"
fi
if [ ! -d "$indent" ]; then
mkdir "$indent"
fi
if [ ! -d "$syntax" ]; then
mkdir "$syntax"
fi
fi
This is executing as a provision.sh script for Vagrant so as far as I know it should run as root. I can see the echo'd message so it's taking the first branch. But for the life of me I can't seem to get this to work; no complaints but the directories don't get created. If I set those variables on an interactive prompt, I need to do sudo mkdir ftdetect (etc.) to get the directories created. Strangely I don't need to sudo to get the .vim directory created--at least that's what I recall.
I tried
if [ ! -d "${basevim}" ]; then
but that didn't do anything. I also tried
basevim="{$HOME}/.vim"
--also no dice. Any thoughts of what I may be missing? As I say, as far as I know it shouldn't be necessary to sudo on a provisioning script on Vagrant. I can tell the script is getting run because those echo'd messages are getting output.
Your script could be replaced by
mkdir -p "$HOME/.vim"/{ftdetect,indent,syntax}
As for the directories not appearing... Where are you looking for them?
Running this as root would create them in root's home directory, /root/, and not in the user's home directory /home/username. When in doubt, use absolute path names (and chown as needed afterwards).

Bash script to change parent shell directory [duplicate]

This question already has answers here:
Why can't I change directories using "cd" in a script?
(33 answers)
Closed 7 years ago.
What I'm trying to do
I've created a shell script that I've added to my $PATH that will download and get everything setup for a new Laravel project. I would like the script to end by changing my terminal directory into the new project folder.
From what I understand right now currently it's only changing the directory of the sub shell where the script is actually running. I can't seem to figure out how to do this. Any help is appreciated. Thank you!
#! /usr/bin/env bash
echo -e '\033[1;30m=========================================='
## check for a directory
if test -z "$1"; then
echo -e ' \033[0;31m✖ Please provide a directory name'
exit
fi
## check if directory already exist
if [ ! -d $1 ]; then
mkdir $1
else
echo -e ' \033[0;31m✖ The '"$1"' directory already exists'
exit
fi
# move to directory
cd $1
## Download Laravel
echo -e ' \033[0;32m+ \033[0mDownloading Laravel...'
curl -s -L https://github.com/laravel/laravel/zipball/master > laravel.zip
## Unzip, move, and clean up Laravel
echo -e ' \033[0;32m+ \033[0mUnzipping and cleaning up files...'
unzip -q laravel.zip
rm laravel.zip
cd *-laravel-*
mv * ..
cd ..
rm -R *-laravel-*
## Make the /storage directory writable
echo -e ' \033[0;32m+ \033[0mMaking /storage directory writable...'
chmod -R o+w storage
## Download and install the Generators
echo -e ' \033[0;32m+ \033[0mInstalling Generators...'
curl -s -L https://raw.github.com/JeffreyWay/Laravel-Generator/master/generate.php > application/tasks/generate.php
## Update the application key
echo -e ' \033[0;32m+ \033[0mUpdating Application Key...'
MD5=`date +”%N” | md5`
sed -ie 's/YourSecretKeyGoesHere!/'"$MD5"'/' application/config/application.php
rm application/config/application.phpe
## Create .gitignore and initial git if -git is passed
if [ "$2" == "-git" ]; then
echo -e ' \033[0;32m+ \033[0mInitiating git...'
touch .gitignore
curl -s -L https://raw.github.com/gist/4223565/be9f8e85f74a92c95e615ad1649c8d773e908036/.gitignore > .gitignore
# Create a local git repo
git init --quiet
git add * .gitignore
git commit -m 'Initial commit.' --quiet
fi
echo -e '\033[1;30m=========================================='
echo -e ' \033[0;32m✔ Laravel Setup Complete\033[0m'
## Change parent shell directory to new directory
## Currently it's only changing in the sub shell
filepath=`pwd`
cd "$filepath"
You can technically source your script to run it in your parent shell instead of spawning a subshell to run it. This way whatever changes you make to your current shell (including changing directories) persist.
source /path/to/my/script/script
or
. /path/to/my/script/script
But sourcing has its own dangers, use carefully.
(Peripherally related: how to use scripts to change directories)
Use a shell function to front-end your script
setup () {
# first, call your big script.
# (It could be open-coded here but that might be a bit ugly.)
# then finally...
cd someplace
}
Put the shell function in a shell startup file.
Child processes (including shells) cannot change current directory of parent process. Typical solution is using eval in the parent shell. In shell script echo commands you want to run by parent shell:
echo "cd $filepath"
In parent shell, you can kick the shell script with eval:
eval `sh foo.sh`
Note that all standard output will be executed as shell commands. Messages should output to standard error:
echo "Some messages" >&2
command ... >&2
This can't be done. Use exec to open a new shell in the appropriate directory, replacing the script interpreter.
exec bash
I suppose one possibility would be to make sure that the only output of your script is the path name you want to end up in, and then do:
cd `/path/to/my/script`
There's no way your script can directly affect the environment (including it's current directory) of its parent shell, but this would request that the parent shell itself change directories based on the output of the script...

exiting script while running source scriptname over SSH

I have a script with a number of options in it one of the option sets is supposed to change the directory and then exit the script however running over ssh with the source to get it to change in the parent it exits SSH is there another way to do this so that it does not exit? my script is in the /usr/sbin directory.
You might try having the script run a subshell instead of whatever method it is using to “change [the directory] in the parent” (presumably you have the child print out a cd command and have the parent do something like eval "$(script --print-cd)"). So instead of (e.g.) a --print-cd option, add a --subshell option that starts a new instance of $SHELL.
d=/path/to/some/dir
#...
cd "$d"
#...
if test -n "$opt_print_cd"; then
sq_d="$(printf %s "$d" | sed -e "s/'/'\\\\''/g")"
printf "cd '%s'\n" "$sq_d"
elif test -n "$opt_subshell"; then
exec "$SHELL"
fi
If you can not edit the script itself, you can make a wrapper (assuming you have permission to create new, persistent files on the ‘server’):
#!/bin/sh
script='/path/to/script'
print_cd=
for a; do test "$a" = --print-cd && print_cd=yes && break; done
if test -n "$print_cd"; then
eval "$("$script" ${1+"$#"})" # use cd instead of eval if the script prints a bare dir path
exec "$SHELL"
else
exec $script" ${1+"$#"}
fi

Resources