.profile has statements to call .bashrc, but .bashrc not executed - bash

I'm using Ubuntu 16.04. In my $HOME/.profile, it has
echo `date` ':.profile executed starts' >> /tmp/testtmp.txt
echo $BASH_VERSION >> /tmp/testtmp.txt
if [ -n "$BASH_VERSION" ]; then
echo 'if 1 entered' >> /tmp/testtmp.txt
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
echo 'if 2 entered' >> /tmp/testtmp.txt
. "$HOME/.bashrc"
fi
else
echo 'if 1 not entered' >> /tmp/testtmp.txt
fi
Every time I login, it never even reaches the first IF.
The test file shows:
Sat Jan 14 05:15:57 EST 2017 :.profile executed starts
if 1 not entered
Sat Jan 14 05:15:57 EST 2017 :.profile executed ends
I echoed $BASH_VERSION, it shows 4.3.46(1)-release. So if if [ -n "$BASH_VERSION" ] is meant to check if that variable exists, (apparently yes), why is it not even reaching the first IF?
From the result, it looks like $BASH_VERSION is not generated until the first time I invoked terminal application.
As those IF statements in .profile are original, I don't understand if $BASH_VERSION is not generated when you login in, what is the purpose to have these statements originally.
Thanks

(This was getting overly long as a comment :) )
See this question on Ask Ubuntu. .profile is probably running under sh, not bash, so BASH_VERSION isn't set in .profile.
To test this, add
ps >> /tmp/testtmp.txt
to your .profile. You will see the process name of the shell you're running under, which may be dash per this.
To see what your default shell is, grep <whatever your username is> /etc/passwd - you will see /bin/<whatever>sh.
If indeed /bin/bash is not set as your default shell, you can change it (per this answer):
sudo chsh -s /bin/bash <whatever your username is>

Related

How do I write a script that shows all aliases upon startup of terminal

I am a new user learning to use Linux. I am currently running Ubuntu 18.04 with several aliases created, and saved in the ~/.bashrc directory. I am trying to write a welcome script that also displays the current aliases upon start up. The current code I have is as follows:
#! /bin/bash
echo -e "\nWelcome $USER"
echo -e "Today's date is: \c"
date
echo -e "\vHave \vA \VGreat \vDay! \c"
echo -e "\nCurrent aliases for reference are:"
alias
Upon startup, or running the script on it's own, the welcome message runs but the actual alias command does not?
First things first:
(...) saved in the ~/.bashrc directory. (...)
Well, I must point that .bashrc is a file, not a directory, and is part of the Bash startup files.
That said, the reason why running the alias command inside a script does not work as expected is that it is a shell builtin, and when invoking it from a script will not behave as if running it from your shell.
Hence, the quickest thing you can do is store your aliases in a different file, like ~/.bash_aliases and ensure it will be loaded by adding this to your .bashrc file:
if [ -f ~/.bash_aliases ]; then
source ~/.bash_aliases
fi
And then read that file directly from your script:
#! /bin/bash
echo -e "\nWelcome $USER"
echo -e "Today's date is: \c"
date
echo -e "\vHave \vA \VGreat \vDay! \c"
echo -e "\nCurrent aliases for reference are:"
cat ~/.bash_aliases

How to check if running as root in a bash script

I'm writing a script that requires root level permissions, and I want to make it so that if the script is not run as root, it simply echoes "Please run as root." and exits.
Here's some pseudocode for what I'm looking for:
if (whoami != root)
then echo "Please run as root"
else (do stuff)
fi
exit
How could I best (cleanly and securely) accomplish this? Thanks!
Ah, just to clarify: the (do stuff) part would involve running commands that in-and-of themselves require root. So running it as a normal user would just come up with an error. This is just meant to cleanly run a script that requires root commands, without using sudo inside the script, I'm just looking for some syntactic sugar.
The $EUID environment variable holds the current user's UID. Root's UID is 0. Use something like this in your script:
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
Note: If you get 2: [: Illegal number: check if you have #!/bin/sh at the top and change it to #!/bin/bash.
A few answers have been given, but it appears that the best method is to use is:
id -u
If run as root, will return an id of 0.
This appears to be more reliable than the other methods, and it seems that it return an id of 0 even if the script is run through sudo.
In a bash script, you have several ways to check if the running user is root.
As a warning, do not check if a user is root by using the root username. Nothing guarantees that the user with ID 0 is called root. It's a very strong convention that is broadly followed but anybody could rename the superuser another name.
I think the best way when using bash is to use $EUID, from the man page:
EUID Expands to the effective user ID of the current user, initialized
at shell startup. This variable is readonly.
This is a better way than $UID which could be changed and not reflect the real user running the script.
if (( $EUID != 0 )); then
echo "Please run as root"
exit
fi
A way I approach that kind of problem is by injecting sudo in my commands when not run as root. Here is an example:
SUDO=''
if (( $EUID != 0 )); then
SUDO='sudo'
fi
$SUDO a_command
This ways my command is run by root when using the superuser or by sudo when run by a regular user.
If your script is always to be run by root, simply set the rights accordingly (0500).
My one-liner:
if [ "$(id -u)" -ne 0 ]; then echo "Please run as root." >&2; exit 1; fi
In this answer, let it be clear, I presume the reader is able to understand the difference betweeen modern shells like bash, zsh and others vs portable POSIX shells like dash.
I believe there is not much to explain here since the highly voted answers do a good job of explaining much of it.
Yet, if there is anything to explain further, don't hesitate to comment, I will do my best by filling the gaps.
Optimized all-round solution for performance and reliability; all shells compatible
New solution:
# bool function to test if the user is root or not
is_user_root () { [ "${EUID:-$(id -u)}" -eq 0 ]; }
Benchmark (save to file is_user_root__benchmark)
#+------------------------------------------------------------------------------+
#| is_user_root() benchmark |
#| "Bash is fast while Dash is slow in this" |
#| Language: POSIX shell script |
#| Copyright: 2020-2021 Vlastimil Burian |
#| M#il: info[..]vlastimilburian[..]cz |
#| License: GPL 3.0 |
#| Version: 1.2 |
#+------------------------------------------------------------------------------+
readonly iterations=10000
# intentionally, the file does not have an executable bit, nor it has a shebang
# to use it, just call the file directly with your shell interpreter like:
# bash is_user_root__benchmark ## should take a fraction of one second
# dash is_user_root__benchmark ## could take around 10 seconds
is_user_root () { [ "${EUID:-$(id -u)}" -eq 0 ]; }
print_time () { date +"%T.%2N"; }
print_start () { printf '%s' 'Start : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }
printf '%s\n' '___is_user_root()___'; print_start
i=1; while [ "$i" -lt "$iterations" ]; do
is_user_root
i=$((i+1))
done; print_finish
Examples of use and duration:
$ dash is_user_root__benchmark
___is_user_root()___
Start : 03:14:04.81
Finish : 03:14:13.29
$ bash is_user_root__benchmark
___is_user_root()___
Start : 03:16:22.90
Finish : 03:16:23.08
Explanation
Since it is multitude times faster to read the $EUID standard bash variable, the effective user ID number, than executing id -u command to POSIX-ly find the user ID, this solution combines both into a nicely packed function. If, and only if, the $EUID is for any reason not available, the id -u command will get executed, ensuring we get the proper return value no matter the circumstances.
Why I post this solution after so many years the OP has asked
Well, if I see correctly, there does seem to be a missing piece of code above.
You see, there are many variables which have to be taken into account, and one of them is combining performance and reliability.
Portable pure POSIX solution + Example of usage of the above function
#!/bin/sh
# bool function to test if the user is root or not (POSIX only)
is_user_root ()
{
[ "$(id -u)" -eq 0 ]
}
if is_user_root; then
echo 'You are the almighty root!'
# You can do whatever you need...
else
echo 'You are just an ordinary user.' >&2
exit 1
fi
Conclusion
As much as you possibly don't like it, the Unix / Linux environment has diversified a lot. Meaning there are people who like bash, zsh, and other modern shells so much, they don't even think of portability (POSIX). It is nowadays a matter of personal choice and needs.
There is a simple check for the user being root.
# Fancy red-colored `error` function with `stderr` redirection with `exit`.
error ()
{
{ printf '\E[31m'; echo "$#"; printf '\E[0m'; } >&2
exit 1
}
# Test for root user.
if [ "$EUID" -eq 0 ]; then
error "Do not run this as the root user"
fi
This also assumes that you want to exit with a 1 if you fail. The error function is some flair that sets output text to red (not needed, but pretty classy if you ask me).
As #wrikken mentioned in his comments, id -u is a much better check for root.
In addition, with proper use of sudo, you could have the script check and see if it is running as root. If not, have it recall itself via sudo and then run with root permissions.
Depending on what the script does, another option may be to set up a sudo entry for whatever specialized commands the script may need.
1- Read official GNU Linux documentation, there are many ways to do it correctly.
2- make sure you put the shell signature to avoid errors in interpretation:
#!/bin/bash
3- this is my script
#!/bin/bash
if [[ $EUID > 0 ]]; then
echo "Please run as root/sudo"
exit 1
else
#do your stuff
fi
Very simple way just put:
if [ "$(whoami)" = "root" ]; then
# you are root
else
# you are not root
fi
The benefit of using this instead of id is that you can check whether a certain non-root user is running the command, too; eg.
if [ "$(whoami)" = "john" ]; then
# you are john
else
# you are not john
fi
Editor's Note: Either prefer using POSIX-compatible test command and comparison [... = ...] or you can use Bash/+other shells specific [[... == ...]].
One simple way to make the script only runnable by root is to start the script with shebang:
#!/bin/su root
If the script really requires root access then its file permissions should reflect that. Having a root script executable by non-root users would be a red flag. I encourage you not to control access with an if check.
chown root:root script.sh
chmod u=rwx,go=r script.sh
Try the following code:
#!/bin/sh
if [ "$(id -u)" -ne 0 ]; then
echo "Sorry, you are not root." >&2
exit 1
fi
Note on edit: Backticks are considered deprecated by now (many further notes).
The problem using: id -u, $EUID and whoami, is all of them give false positive when I fake the root, like this:
$ fakeroot
id:
$ id -u
0
$EUID:
$ echo $EUID
0
whoami:
$ whoami
root
Then a reliable (and hacking) way is verify if the user has access to the /root directory:
$ ls /root >/dev/null 2>&1 && is_root=true || is_root=false; echo "$is_root"
id -u is much better than whoami, since some systems like Android may not provide the word root.
Example command:
# whoami
Example output:
whoami: unknown uid 0
As far as I know, the correct way to check it, is as follows:
#!/bin/sh
if [ "$(id -u)" -eq 0 ]; then
echo "You are root."
else
echo "You are NOT root." >&2
fi
OP's Note: you may see "Testing For Root" section on linuxcommand.org.
Editor's Note: I have slightly adjusted this shell snippet to be POSIX-compatible.
Check if you are root and quit if you are not:
if ((EUID != 0)); then
echo "Root or Sudo Required for script ( $(basename $0) )"
exit
fi
Or in this example, try to create a directory in root location then try after rights were elevated.
Check if you are root and if not elevate if possible :
# Fails to create these dirs (needs sudo)
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)
if ((EUID != 0)); then
echo "Granting root privileges for script ( $(basename $0) )"
if [[ -t 1 ]]; then
sudo "$0" "$#"
else
exec 1> output_file
gksu "$0" "$#"
fi
exit
fi
echo "Root privileges granted..."
# Creates Dirs as it now has rights
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)
It is important to notice that whenever you run a script using sudo the 'user context' or environment will switch to root.
But Teo what that means?
Well, my young padawan, this means that if a padawan user runs a script that contains a tilde (~) using sudo, whenever the bash will expand ~ the result will be /root and not /home/<user> (i.e., in this case /home/padawan), or if you create either a directory or a file the owner and group will be root and not the that executed the script in this case padawan, because the user environment was switched.
For instance, lets check this script install-app.sh:
#!/bin/bash
ROOT_UID=0 # Only users with $UID 0 have root privileges.
E_NOTROOT=87 # Non-root exit error.
## Prevent the execution of the script if the user has no root privileges
if [ "${UID:-$(id -u)}" -ne "$ROOT_UID" ]; then
echo 'Error: root privileges are needed to run this script'
exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
service mysql start
...
If we run using sudo:
sudo install-app.sh
This will create directories and a config file will look like this:
##
## ~ (/root)
drwxr-xr-x 17 root root 4096 Nov 23 20:45 ./
drwxr-xr-x 5 root root 4096 Nov 15 19:04 ../
...
drwxr-xr-x 3 root root 4096 Nov 25 14:30 app/
...
drwxr-xr-x 2 root root 4096 Nov 16 19:08 tmp/
## ~/app (/root/app)
drwxr-xr-x 3 root root 4096 Nov 25 14:30 ./
drwxr-xr-x 17 root root 4096 Nov 25 14:33 ../
drwxr-xr-x 2 root root 4096 Nov 25 14:33 init/
## ~/app/init (/root/app/init)
drwxr-xr-x 2 root root 4096 Nov 25 14:33 ./
drwxr-xr-x 3 root root 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root root 0 Nov 25 14:33 config
## /home/<user>/app/conf
drwxr-xr-x 2 <user> <user> 4096 Nov 25 14:43 ./
drwxr-xr-x 3 <user> <user> 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root root 0 Nov 25 14:43 profile
As you can she the script is a total mess. Now the <user> cannot get access to the profile file neither can modify the config without sudo. At the beginning seams to be something not important but trust me if your project gets bigger someone will run the script and mess with your system.
Recommendation
My recommendation will be: request to the user to verify if is a sudoer or not. Then, add sudo to the commands that require it.
Applying this changes to the script will be like this:
#!/bin/bash
E_NOTROOT=87 # Non-root exit error.
## Prevent the execution of the script if the user has no root privileges
## Check if is sudoer
if ! $(sudo -l &>/dev/null); then
echo 'Error: root privileges are needed to run this script'
exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
sudo service mysql start
...
This modification allows the user to run the script like this:
install-app.sh
The user will be requested to insert his password to verify if is sudoer. After,mkdir -vp ~/app/init will create the file in the user's home:
/home/<user>/app/init
/home/<user>/app/init/config
/home/<user>/app/init/profile
Also, I recommend to get the users homer directory and use it as a constant.
## Defines user home directory
USER_HOME_DIR=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6)
...
mkdir -vp "$USER_HOME_DIR/app/init"
...
I stumbled on the same issue. The line #!/bin/su root would be an elegant method, but does not work on certain (higher) versions of bash, as mentioned by #basickarl. Further - this method will probably fail when you start the script with /bin/bash ./some_script.(b)sh.
I found an other page on SO where the use of the environment variables SUDO_UID and SUDO_USER were used. When a normal user invokes a script with sudo these are available in the script. Otherwise they are empty. Also: when you are actually logged on as root these values are empty (or unset - not entirely sure) as well.
So this is the solution I'm currently using:
isSudo()
{
local _fn="${FUNCNAME[0]}"
if [[ $(/usr/bin/id -u) -eq 0 ]] ; then
if [[ ! -z "$SUDO_UID" && ! -z "$SUDO_USER" ]] ; then
>2 echo -e "$_fn: invoked as sudo-user ($SUDO_USER)."
else
>2 echo -e "$_fn: invoked as root ($SUDO_USER)."
fi
return 0
fi
>2 echo "$_fn: not as root or as sudoer."
return 1
}
Then use it like this eg.:
if $(isSudo) ; then
echo -e "Script started as root or as sudoer."
else
echo -e "Script not started as root or with sudo"
fi
The >2 in front of the echo is to redirect the echo to stderr otherwise the if statement goes haywire and it's just for a little debugging. In stead of using an echo, you could save "root", "sudoer" or "user" in a local variable and let the function echo that back and then perform a case on that like this:
how_invoked()
{
local _invoked_as="USER"
if [[ $(/usr/bin/id -u) -eq 0 ]] ; then
if [[ ! -z "$SUDO_UID" && ! -z "$SUDO_USER" ]] ; then
_invoked_as="SUDOER"
else
_invoked_as="ROOT"
fi
fi
echo -n "$_invoked_as" # -n prevents newline
}
And then use it like this:
INVOKED_AS=$(how_invoked)
case $INVOKED_AS in
USER)
echo -e "Invoked as user." ;;
SUDOER)
echo -e "Invoked as sudoer." ;;
ROOT)
echo -e "Invoked as root." ;;
*)
echo -e "I'm confused" ;;
esac
Or if you just want to test for one of those:
if [ "$(how_invoked)" == "SUDOER" ] ; then
echo -e "You are a sudoer."
else
echo -e "You are NOT a sudoer."
fi
Hope this helps.
My one-liner:
[ "$(whoami)" != root ] && echo "Please, run as root." >&2 && exit 1
Tested under Debian, Ubuntu and Docker.
My two cents, running in Bash:
#!/bin/bash
# Display the UID variable
echo "Your UID is $UID"
# Check for root user via UID
if [ "$UID" -eq 0 ]; then
echo "You are root"
else
echo "You are not root user" >&2
fi
My check for the root user, running in Bash:
#!/bin/bash
if [ "$UID" -eq 0 ]; then
echo "You are root."
else
echo "You are just an ordinary user." >&2
fi

Cron job does NOT get the environment variables set in .bashrc

Here is my cron job:
plee#dragon:~$ crontab -l
* * * * * /bin/bash -l -c 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test'
and inside ~/.bashrc file, I have export EDITOR=vim, but in the final /tmp/cronjob.test file, it's still empty?
So how can I get the environment variables (set in .bashrc file) and use it in my cron job?
plee#dragon:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 12.04 LTS
Release: 12.04
Codename: precise
plee#dragon:~$ uname -a
Linux dragon 3.2.0-26-generic-pae #41-Ubuntu SMP Thu Jun 14 16:45:14 UTC 2012 i686 i686 i386 GNU/Linux
If use this:
* * * * * /bin/bash -l -c -x 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test' 2> /tmp/cron.debug.res
In /tmp/cron.debug.res:
...
++ return 0
+ source /home/plee/.bashrc
++ '[' -z '' ']'
++ return
+ echo
BTW, the .bashrc file is the default one came with Ubuntu 12.04, with the exception that I added one line export EDITOR=vim.
If I don't use the cron job, instead, just directly do this on the command line:
source .bashrc; echo $EDITOR # Output: vim
The reason for source ~/.bashrc not working is the contents on your ~/.bashrc (default one from Ubuntu 12.04). If you look in it you will see on lines 5 and 6 the following:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
PS1 variable is set for an interactive shell, so it's absent when run via cron, even though you are executing it as a login shell. This is confirmed by contents of the file produced by /bin/bash -l -c -x 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test':
+ source /home/plee/.bashrc
++ '[' -z '' ']'
++ return
To make source ~/.bashrc work, comment out the line that checks for presence of the PS1 variable in ~/.bashrc:
#[ -z "$PS1" ] && return
This will make bash execute the entire contents of ~/.bashrc via cron
Answer provided by #alex is correct but in Ubuntu 13.10 the code has been modified a little. There is no $PS1 variable but in lines 6-9 there is a code
case $- in
*i*) ;;
*) return;;
esac
Just commenting out the line which returns works. i.e. the code below works
case $- in
*i*) ;;
# *) return;;
esac
I just tried a file .env_setup_rc file with only one line export EDITOR=vim, surprisingly it's working.
So I guess there is something in .bashrc conflicting with the cron job bash command.

How to get shell to self-detect using zsh or bash

I've a question on how to tell which shell the user is using. Suppose a script that if the user is using zsh, then put PATH to his .zshrc and if using bash should put in .bashrc. And set rvmrc accordingly.
#!/usr/bin/env bash
export PATH='/usr/local/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
I've tried the following but it does not work : (
if [[ $0 == "bash" ]]; then
export PATH='/usr/local/bin:$PATH' >> ~/.bashrc
elif [[ $0 == "zsh" ]]; then
export PATH='/usr/local/bin:$PATH' >> ~/.zshrc
fi
# ... more commands ...
if [[ $0 == "bash" ]]; then
[[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm' >> ~/.bashrc
source ~/.bashrc
elif [[ $0 == "zsh" ]]; then
[[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm' >> ~/.zshrc
source ~/.zshrc
fi
If the shell is Zsh, the variable $ZSH_VERSION is defined. Likewise for Bash and $BASH_VERSION.
if [ -n "$ZSH_VERSION" ]; then
# assume Zsh
elif [ -n "$BASH_VERSION" ]; then
# assume Bash
else
# assume something else
fi
However, these variables only tell you which shell is being used to run the above code. So you would have to source this fragment in the user's shell.
As an alternative, you could use the $SHELL environment variable (which should contain absolute path to the user's preferred shell) and guess the shell from the value of that variable:
case $SHELL in
*/zsh)
# assume Zsh
;;
*/bash)
# assume Bash
;;
*)
# assume something else
esac
Of course the above will fail when /bin/sh is a symlink to /bin/bash.
If you want to rely on $SHELL, it is safer to actually execute some code:
if [ -n "$($SHELL -c 'echo $ZSH_VERSION')" ]; then
# assume Zsh
elif [ -n "$($SHELL -c 'echo $BASH_VERSION')" ]; then
# assume Bash
else
# assume something else
fi
This last suggestion can be run from a script regardless of which shell is used to run the script.
Just do echo $0
it says -zsh if it's zsh and -bash if it's bash
EDIT: Sometimes it returns -zsh and sometimes zsh and the same with bash, idk why.
A word of warning: the question you seem to have asked, the question you meant to ask, and the question you should have asked are three different things.
“Which shell the user is using” is ambiguous. Your attempt looks like you're trying to determine which shell is executing your script. That's always going to be whatever you put in the #! line of the script, unless you meant your users to edit that script, so this isn't useful to you.
What you meant to ask, I think, is what the user's favorite shell is. This can't be determined fully reliably, but you can cover most cases. Check the SHELL environment variable. If it contains fish, zsh, bash, ksh or tcsh, the user's favorite shell is probably that shell. However, this is the wrong question for your problem.
Files like .bashrc, .zshrc, .cshrc and so on are shell initialization files. They are not the right place to define environment variables. An environment variable defined there would only be available in a terminal where the user launched that shell and not in programs started from a GUI. The definition would also override any customization the user may have done in a subsession.
The right place to define an environment variable is in a session startup file. This is mostly unrelated to the user's choice of shell. Unfortunately, there's no single place to define environment variables. On a lot of systems, ~/.profile will work, but this is not universal. See https://unix.stackexchange.com/questions/4621/correctly-setting-environment and the other posts I link to there for a longer discussion.
You can simply try
echo $SHELL
the other answers fail with set -u
if [ ! -z ${ZSH_VERSION+x} ]; then
echo "this is zsh"
echo ${(%):-%x}
elif [ ! -z ${BASH_VERSION+x} ]; then
echo "this is bash"
echo $BASH_SOURCE
else
echo "not recognized"
fi
An alternative, might not work for all shells.
for x in $(ps -p $$)
do
ans=$x
done
echo $ans
Myself having a similar problem, settled for:
_shell="$(ps -p $$ --no-headers -o comm=)"
if [[ $_shell == "zsh" ]]; then
read -q -s "?Do it?: "
fi
elif [[ $_shell == "bash" || $_shell == "sh" ]]; then
read -n 1 -s -p "Do it [y/n] "
fi
Here is how I am doing it based on a previous answer from Gilles :
if [ -n "$ZSH_VERSION" ]; then
SHELL_PROFILE="$HOME/.zprofile"
else
SHELL_PROFILE="$HOME/.bash_profile"
fi
echo "export VAR1=whatever" >> $SHELL_PROFILE
echo "INFO: Refreshing your shell profile: $SHELL_PROFILE"
if [ -n "$ZSH_VERSION" ]; then
exec zsh --login
else
source $SHELL_PROFILE
fi

Adding a function to /etc/profile causes gnome to restart after login

I recently added the following bash function definition to my /etc/profile in Ubuntu 11.04 (it's a function to shortcut a CD command to a specific development directory):
################## JMOZTELEPORT BEGIN ##################
function JMozTeleport() {
version=0.4.58
pathtopythonpackages=`python -c "from site import getsitepackages; print getsitepackages()[0]"`
pathtopythonteleport="$pathtopythonpackages/JMozTools-$version-py2.7.egg/JMozTools/JMozTeleport.py"
# $1 is the command to run
isversion=0
ishelp=0
if [[ "$1" == "-v" || "$1" == "--version" ]]
then
isversion=1;
fi
if [[ "$1" == "-h" || "$1" == "--help" ]]
then
ishelp=1;
fi
if [ -z $1 ]
then
python "$pathtopythonteleport" "-h"
elif [ $1 == "version" ]
then
echo $version
elif [ $isversion == 1 -o $ishelp == 1 ]
then
python "$pathtopythonteleport" "$#"
else
cd $(python "$pathtopythonteleport" "$#")
fi
}
################### JMOZTELEPORT END ###################
Once I do this, though, (which works fine if I source /etc/profile from a terminal shell), I am unable to login to Gnome. It logs in ok, but then it immediately closes Gnome and brings me back to the login screen. If I remove this stuff from my /etc/profile, it again allows me to login fine.
I'm confused as to what is causing this to make gnome restart. Any ideas as to where the problem is?
/etc/profile is sourced by /bin/sh, something that probably happens during Gnome startup. It's probably choking on the [[ ... ]] syntax, which is bash-specific. (/bin/sh may or may not be a symlink to /bin/bash, depending on the system).
Since your function appears to be bash-specific, you might consider putting it in /etc/bash.bashrc rather than /etc/profile, or perhaps even $HOME/.bashrc. (Do you need it in non-interactive shells?)
You put it under debug and see what is causing it to restart. Use, the set -x command to enable debug mode. Similarly the set +x command disables it.
Putting set -x at the top of your /etc/profile should cause debug information to be printed out.

Resources