Why my file does not get sourced from bash script? - bash

I have a bash script where at some point, I want to source the ${HOME}/.profile file which should add ${HOME}/.local/bin to the $PATH. But when I check the path with echo $PATH, ${HOME}/.local/bin is absent as if the source did not happen. What am I doing wrong?
if command -v pip3 &>/dev/null; then
echo "Pip is already installed."
else
echo "Pip is not installed. Installing Pip..."
cd ${HOME}/Downloads
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
su -c "python3 get-pip.py --user" "$SUDO_USER"
cat <<-'EOT' >> "${HOME}/.profile"
# set PATH so it includes user's private .local/bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
EOT
source "${HOME}/.profile" #this is not happening!!!
rm ${HOME}/Downloads/get-pip.py
echo "Pip has been installed."
fi
Thanks in advance.
EDIT: Fixed the script syntax as suggest by Kusalananda.

A script can't modify the environment of the shell from whence it was executed.
Sourcing ~/.profile in the script will not set the path in the interactive shell that originally started the script. To do that, you would have to source your script.
Also, your here-document would need to be quoted, or the current values of HOME and PATH would be inserted into the .profile file:
cat <<'PROFILE_END' >> "$HOME/.profile"
# set PATH so it includes user's private .local/bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
PROFILE_END
Also note that if the user is a bash user with an existing ~/.bash_profile file, then the ~/.profile file will be ignored for that user when a new login shell is started.
I'm further unsure why you su to $USER. It seems like an unnecessary step.

Related

bad interpreter no such file or directory

Thank you for reviewing my shell script i am producing this error but not sure why it is not running. I am a noob when it comes to shell scripting. Please help. Here is my code:
#!/bin/bash
#This script creates the log files based on the current date and hour
#Variables for managing the logs
LOG_DIRECTORY=/var/log; export LOG_DIRECTORY
LOG_DIRECTORY_FILE=/var/log/secure; export LOG_DIRECTORY_FILE
MY_LOG_DIRECTORY=$LOG_DIRECTORY/mylogs; export MY_LOG_DIRECTORY
MY_LOG_FILE=$MY_LOG_DIRECTORY/mylog-`date +%m-%d-%H`; export MY_LOG_FILE
EXPRESSTION=`date '+%b %d %H'`; export MY_LOG_FILE
#Checks if mylog directory exists.If not, then creates it
if [ ! -d "$MY_LOG_DIRECTORY" ]; then
mkdir -p $MY_LOG_DIRECTORY
fi
#Scripts exits successfully, If the log already exists
if [ -f "$MY_LOG_FILE" ]; then
echo "Log file already exists. Nothing is written to log";
exit 0;
fi
#grep the contents to the log file
grep "^$EXPRESSTION" $LOG_DIRECTORY_FILE >> $MY_LOG_FILE
echo "New myLog file created successfully"
Your script needs to be saved as a UNIX text file.
Try running dos2unix on it, or open it up in vim and run :set fileformat=unix and save.
If you don't have dos2unix, and aren't comfortable with vim, you can use perl:
perl -pi -e 's/\r\n?/\n/g' your-script-filename
"bad interpreter no such file or directory" error indicates /bin/bash does not exist.
Try to run script as
$ sh log.sh
OR use some other available shell interpreter (e.g /bin/sh , /bin/ksh) instead of /bin/bash

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 ruby command not found

Every time I log into my VPS I must run source ~/.bashrc before I can run any rvm, ruby, or gem commands.
Why is this? Can't make it load by default?
ssh deployer#xxx
ruby -v
-bash: ruby: command not found
source ~/.bashrc
ruby -v
ruby 1.9.3p429 (2013-05-15 revision 40747) [i686-linux]
I installed rvm under deployer.
I have ~/.bash_pofile which is empty. I also have ~/.profile which has the following in it:
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
My ~/.bashrc has this at the top:
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
From the bash man page:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
So in your case, the (empty) ~/.bash_profile is being executed, and your ~/.profile (and thus your ~/.bashrc) are ignored. To solve this, you'll either need to delete your ~/.bash_profile, or else move the contents of ~/.profile into ~/.bash_profile.
When you log in, if Bash can find a file named .bash_profile in your home directory it will execute it and do not even search for a .profile file. Thus you have two choices, either remove the empty .bash_profile file or copy the contents of .profile to .bash_profile.
Moving the information from .bashrc to the other files, as suggested by others is one way to do it.
Otherwise, this snippet of code will do the same thing, without needing to move the contents, or remove the file. Depending on the ways you have things set up, you may not want to delete a file, if it has relevant information in it for other tasks, other than interactive login.
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Though using the files as they are intended to be used by reading the documentation can definitely alleviate some frustration.

chsh: Operation is not supported by the directory node when trying to change shell to zsh

I'm trying to install zsh as my shell.
I've used curl to get the files.
curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh
But when it gets to changing the shell it gives me...
chsh: Operation is not supported by the directory node. Operation is not supported by the directory node.
chsh: no changes made
Any ideas why this would be happening would be appreciated.
First thing would be to try changing the shell from your command line...
chsh -s `which zsh`
I have the following code to deal with a similar situation (not being able to change login shell at a work cluster). It starts zsh from bash, with some care taken about it ("works for me")
# for hosts matching the silly name... start zsh from bash
if [[ `uname -n` == foo-[0-9][0-9].bar.foobar.bar ]]; then
if [[ -x `which --skip-alias zsh 2>/dev/null` ]]; then
if [ -z $ZSH_STARTED ]; then
export ZSH_STARTED="true"
zsh
fi
fi
fi

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...

Resources