How to start a shell without any user configuration? - linux

I need to use a "clean" shell (e.g. bash) under Linux/OSX terminal without any user configuration, but it reads config info from some files (e.g ~/.bashrc) every time it starts. I can modify the file every time I need a "clean" shell, and revert it back when I finished, but is there any easier ways to do this, for example a command?

Running bash --noprofile --norc still inherited from parent process. Based on a similar question I found that the way I interpreted this question env -i bash --norc --noprofile was what I would want.

You can pass the --noprofile and --norc command-line options:
$ bash --noprofile --norc
You will find documentation about these options in the man page.

Use --noprofile --norc:
--noprofile
Do not read either the system-wide startup file /etc/profile or any of the personal initializa‐
tion files ~/.bash_profile, ~/.bash_login, or ~/.profile. By default, bash reads these files
when it is invoked as a login shell (see INVOCATION below).
--norc Do not read and execute the system wide initialization file /etc/bash.bashrc and the personal
initialization file ~/.bashrc if the shell is interactive. This option is on by default if the
shell is invoked as sh.
(from the manpage).

It is often desirable to launch an entirely blank bash:
no environment variables carried from the parent shell;
an empty home dir without any package-specific configuration files (e.g. .gitconfig and .local/...);
no shell configuration files.
This works for me both on MacOS and Linux:
env -i HOME=$(mktemp -d) bash --noprofile --norc
cd
In that bash shell, the HOME dir is that test dir just created (change the name if needed), and there are no particular settings. The only environment variables that are set are PWD, HOME, and SHLVL.
Upon starting bash, the PWD is where we were before, so we need to do that initial cd.
Example (Linux):
$ env -i HOME=$(mktemp -d) bash --noprofile --norc
bash-5.0$ cd
bash-5.0$ pwd
/tmp/tmp.mwgHRQE1aJ
bash-5.0$ printenv
PWD=/tmp/tmp.mwgHRQE1aJ
HOME=/tmp/tmp.mwgHRQE1aJ
SHLVL=1
OLDPWD=/home/xxxxxxxxxxxxxxxxx
_=/usr/bin/printenv
bash-5.0$

Related

How to Change my default shell on server?

I was assigned an account for log in to a remote server, and I want to change my default shell.
I tried chsh command but it says: chsh: "/public/home/{my_id}/bin/zsh" is not listed in /etc/shells.
If you don't have permission to install zsh system wide, a quick fix is to append exec ~/bin/zsh -l to ~/.bash_profile (if bash is the current shell), or an equivalent rc file for the current login shell.
zsh -l starts zsh as a login shell.
exec COMMAND replaces the current process with COMMAND, so you'll only have to type exit (or press ctrl+d) once.
~/.bash_profile is executed when bash starts as a login shell, you can still run command bash normally.
Depending what is in ~/.bash_profile (or equivalent), you may wish to avoid executing its other contents, by putting exec ~/bin/zsh -l at the start of the file (not the end), and copy/port anything important over to the zsh equivalent, $ZDOTDIR/.zprofile.
I might also do export SHELL="$HOME/bin/zsh", although I'm unsure of the full effects of setting SHELL differently to that specified for your user in /etc/passwd, to a shell not in /etc/shells, and to a shell binary in your home path.
First check all the shells available on your linux system
cat /etc/shells
Use chsh command line utility for changing a login shell with the -s or –shell option like this.
# chsh --shell /bin/sh tecmint

Command NOT found when called from inside bash script

I have an application named puppet installed on my Linux box. It is installed at location /usr/test/bin/puppet
This is how .bash_profile looks
export PATH=/usr/test/bin
if I run command puppet apply from console, it works fine but when I call puppet command from inside bash script, it says command not found
#!/bin/bash
puppet apply x.pp
Any ideas on what is wrong ?
.bash_profile is loaded only if bash is invoked as login shell (bash -l or from a real tty), at least in Debian based distributions bash in a virtual tty (for example when using xterm, gnome-terminal, etc...) is invoked as interactive shell.
Interactive shells loads the configuration from ~/.bashrc.
bash manpage:
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
Shellscripts don't load any of these.
You can check which files are opened by any program with strace:
strace ./s.sh 2>&1 | grep -e stat -e open
Possible solutions:
You can export the variable at the beginning of every script:
#!/bin/bash
export PATH=$PATH:...
Or you can have another file with the desired variables and source it from any script that need those:
/etc/special_vars.sh:
export PATH=$PATH:...
script:
#!/bin/bash
. /etc/special_vars.sh
puppet ...
Configure the PATH in in ~/.bashrc, ~/.bash_profile and ~/.profile for the user running the script (sub-processes will inherit the environment variables) to have some warranty that the user can run the script from different environments and shells (some bourne compatible shells others than bash do load ~/.profile)
Maybe the export of PATH is wrong?
export PATH=$PATH:/usr/test/bin/puppet
You could try using an alias, like so
in your .bash_profile:
alias puppet='bash puppet.fileextension'
you can also do
alias puppet='bash path/to/puppet.fileextension'
which will let you run the script from anywhere in Terminal.
EDIT:
OP has stated in the comments that there will be two different systems running, and he asked how to check the file path to the bash file.
If you do
#!/bin/bash
runPuppet(){
if [ -e path/to/system1/puppet.fileextension]
then
bash path/to/system1/puppet.fileextension $1 $2
elif [ -e path/to/system2/puppet.fileextension]
then
bash path/to/system2/puppet.fileextension $1 $2
fi
}
runPuppet apply x.pp
and change the runPuppet input to whatever you'd like.
To clarify/explain:
-e is to check if the file exists
$1 & $2 are the first two input parameters, respectively.

Strange behavior of .bashrc

I changed .bashrc file on my web server a little bit, to color links on ls -la and so on. But when I log in using ssh: ssh user#server and type ls -al nothing is coloring, seems like my .bashrc file has not been applied on login. When if I just type bash and then again ls -la - all works fine. In short, all my rules in .bashrc only apllied when I type bash just after authorization, a little boring.
When you log in via ssh, you invoke a login shell. When you type bash in an existing shell, you invoke an interactive shell.
.bash_profile is read when a login shell is invoked, and .bashrc is read when an interactive shell is invoked.
Try adding this to your .bash_profile:
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
See bash(1) for more details.
~/.bashrc is only read if the shell is interactive and not a login shell:
When an interactive shell that is not a login shell is started, bash reads and executes commands from
/etc/bash.bashrc and ~/.bashrc, if these files exist.
Furthermore:
Bash attempts to determine when it is being run with [...] sshd. If bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc and ~/.bashrc, if
these files exist and are readable. It will not do this if invoked as sh.
So:
your remote shell must be bash, not sh,
it must not be a login shell, and
it must be an interactive shell.

How can I debug the bash prompt?

I've been editing .bashrc files and other init files, and it seems that I've left behind a few code snippets or two that are causing a few errors at the prompt (e.g. file missing), but I can't find them.
How do I debug the prompt to find out what init scripts I've carelessly hacked?
Most of the shells have debug flags that show the commands being executed. Bash may even have one that shows a command before expansion of variables and after. Have you tried checking (I believe) -c -x or -X flags and see if they show the information you are looking for.
You can set them as first thing in the rc files (most global one) or just pass it down into bash command by invoking it from another shell.
In fact, if you invoke bash from another shell, you can also use script command to record everything you see and do into the file, which makes postmortem analysis so much easier.
Try invoking bash with the -x flag, then sourcing your .bashrc or .bash_profile or whatever you're using. That ought to be prolix enough to find your problem
ie:
bash -x
source .bashrc
The easiest way to get a clean initial state is to SSH into your current host, but instead of letting SSH launch your shell with default settings, you provide an explicit command which prevents .bashrc from being read.
ssh -tt localhost /bin/bash --norc
The -tt forces SSH to allocate a TTY, which is what would normally happen when you open a shell connection, but is not default when running an explicit command.
The --norc prevents bash from reading your settings file (since we want to do that ourselves).
You should now be at a bash prompt, in a clean environment. This is useful for examining what variable are set to before your .bashrc runs etc. Enable tracing and source your .bashrc:
set -x # Enable tracing
source .bashrc
Try to see where you've defined prompt - probably it in some dot file in your home directory:
grep PS1 ~/.*
You can see current value of prompt by just printing it:
echo $PS1
HTH
Check the .bash_history file in your home directory to find out what commands you have been running. If you used commands like vi filename to open the init scripts, it will find them in the command history.

Setting Enviroment Variables Dynamically on Linux

I am currently looking for a way to set enviroment variables in Linux via a simple shell script. Within the script I am currently using the 'export' command, however this only has scope within the script where system-wide scope is needed.
Is there anyway I can do this via a shell script, or will another method need to be used?
When you run a shell script, it executes in a sub-shell. What you need is to execute it in the context of the current shell, by sourcing it with:
source myshell.sh
or:
. myshell.sh
The latter is my preferred approach since I'm inherently lazy.
If you're talking about system-wide scope inasmuch as you want to affect everybody, you'll need to put your commands in a place where they're sourced at login time (or shell creation time), /etc/profile for example. Where you put your commands depends on the shell being used.
You can find out what scripts get executed by examining the man page for your shell:
man bash
The bash shell, when invoked as a login shell (including as a non-login shell but with the --login parameter), will use /etc/profile and the first of ~/.bash_profile, ~/.bash_login or ~/.profile.
Non-login bash shells will use. unless invoked with --norc or --rcfile <filename>, the files /etc/bash.bashrc and ~/.bashrc.
I'm pretty certain it's even more convoluted than that depending on how the shell is run, but that's as far as my memory stretches. The man page should detail it all.
You could have your script check for the existence of something like /var/myprog/env-vars-to-load and 'source' it then unlink it if it exists, perhaps using trap and a signal. Its hard to say, I'm not familiar with your program.
There is no way to 'inject' environmental variables into another process' address space, so you'll have to find some method of IPC which will can instruct the process on what to set.
A fundamental aspect of environment variables is that you cannot affect the environment for any process but your own and child processes that you spawn. You can't create a script that sets "system wide" environment variables that somehow become usable by other processes.
On the shell prompt:
$ source script.sh
And set the env vars in script.sh
test.sh
#!/bin/bash
echo "export MY_VAR=STACK_OVERFLOW" >> $HOME/.bashrc
. $HOME/.bashrc
sh task.sh
task.sh
#!/bin/sh
echo $MY_VAR
Add executable rights:
chmod +x test.sh task.sh
And lauch test.sh
./test.sh
Result:
STACK_OVERFLOW

Resources