What does this command do?
exec bash -l
I found this command as part of a reminder text file were I wrote some instructions regarding how to create a ssh key and clone a git repo, but I wrote it a long time ago and I can't remember what it does.
exec executes a specified command, replacing the current process rather than starting a new subprocess.
If you type
bash -l
at a shell prompt, it will invoke a new shell process (the -l makes it a login shell). If you exit that shell process, you'll be back to your original shell process.
Typing
exec bash -l
means that the new shell process replaces your current shell process. It's probably slightly less resource intensive.
The reason for doing it is probably so that the new shell sets up its environment (by reading your .bashrc, .bash_profile, etc.).
See the bash documentation for more information:
Bash Startup Files for how a login shell differs from a non-login shell
Bourne Shell Builtins for documentation on the exec command.
(You should be able to read the manual on your own system by typing info bash.)
This will replace your current shell with a new bash shell run as a login shell.
Related
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have a command that runs fine if I ssh to a machine and run it, but fails when I try to run it using a remote ssh command like :
ssh user#IP <command>
Comparing the output of "env" using both methods resutls in different environments. When I manually login to the machine and run env, I get much more environment variables then when I run :
ssh user#IP "env"
Any idea why ?
There are different types of shells. The SSH command execution shell is a non-interactive shell, whereas your normal shell is either a login shell or an interactive shell. Description follows, from man bash:
A login shell is one whose first character of argument
zero is a -, or one started with the --login option.
An interactive shell is one started without non-option
arguments and without the -c option whose standard input
and error are both connected to terminals (as determined
by isatty(3)), or one started with the -i option. PS1 is
set and $- includes i if bash is interactive, allowing a
shell script or a startup file to test this state.
The following paragraphs describe how bash executes its
startup files. If any of the files exist but cannot be
read, bash reports an error. Tildes are expanded in file
names as described below under Tilde Expansion in the
EXPANSION section.
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. The --noprofile option may
be used when the shell is started to inhibit this behav
ior.
When a login shell exits, bash reads and executes commands
from the file ~/.bash_logout, if it exists.
When an interactive shell that is not a login shell is
started, bash reads and executes commands from ~/.bashrc,
if that file exists. This may be inhibited by using the
--norc option. The --rcfile file option will force bash
to read and execute commands from file instead of
~/.bashrc.
When bash is started non-interactively, to run a shell
script, for example, it looks for the variable BASH_ENV in
the environment, expands its value if it appears there,
and uses the expanded value as the name of a file to read
and execute. Bash behaves as if the following command
were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search
for the file name.
How about sourcing the profile before running the command?
ssh user#host "source /etc/profile; /path/script.sh"
You might find it best to change that to ~/.bash_profile, ~/.bashrc, or whatever.
(As here (linuxquestions.org))
Shell environment does not load when running remote ssh command. You can edit ssh environment file:
vi ~/.ssh/environment
Its format is:
VAR1=VALUE1
VAR2=VALUE2
Also, check sshd configuration for PermitUserEnvironment=yes option.
I had similar issue, but in the end I found out that ~/.bashrc was all I needed.
However, in Ubuntu, I had to comment the line that stops processing ~/.bashrc :
#If not running interactively, don't do anything
[ -z "$PS1" ] && return
I found an easy resolution for this issue was to add
source /etc/profile
to the top of the script.sh file I was trying to run on the target system.
On the systems here, this caused the environmental variables which were needed by script.sh to be configured as if running from a login shell.
In one of the prior responses it was suggested that ~/.bashr_profile etc... be used.
I didn't spend much time on this but, the problem with this is if you ssh to a different user on the target system than the shell on the source system from which you log in it appeared to me that this causes the source system user name to be used for the ~.
Just export the environment variables you want above the check for a non-interactive shell in ~/.bashrc.
I've found a very strange issue, when in linux terminal I type "enable -n trap", it would disable the trap linux builtin command. But if I put it into a script like
#!/bin/bash
enable -n trap
and then run the script, there's no error but the command is also not disabled. Really appreciate if someone could share what is happening and how to run it in some file instead of directly in the terminal. Thank you!
The enable command only affects the current shell. When you run a script, that script is executed in a new process, so:
A new shell starts
The enable command runs and disables the trap command in that shell
The shell exits
If you want to affect the current shell, your only option is to source the script using the . (or source) command. If the script is named disable-trap.sh and is in your $PATH, you can run:
. disable-trap.sh
You can also provide a full path to the script:
. /path/to/disable-trap.sh
Sourcing a script like this is largely equivalent to typing the same commands in at the command line: it executes the instructions in the script in the current shell, rather than spawning a new process.
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
I want the following script command to be executed automatically when ever I log in to shell.
script /home/user/mylog_$(date '+%Y%m%d').log
I forget to run this command most of the times :)
Every time you start an interactive login bash shell, it will execute all commands put in ~/.bash_profile
It depends on the particular shell that you are using.
For bash, add the line to ~/.bashrc.
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