Is it possible to source a .bshrc file from .cshrc in a non-interactive session?
I'm asking because tcsh is our default shell at work and the .cshrc has to be used to set up the environment initially.
However, I am not really familiar with the tcsh and I have my own set-up in bash, so right now I have the following lines at the end of my .cshrc file:
if ( $?prompt && -x /bin/bash) then
exec /bin/bash
endif
This works fine, loading my environment from .bashrc and giving me a bash prompt for interactive sessions but now I also need the same set-up for non-interactive sessions, e.g. to run a command remotely via SSH with all the correct PATHs etc.
I can't use 'exec' in that case but I can't figure out how to switch to bash and load the bash config files "non-interactively".
All our machines share the same home directory, so any changes to my local *rc files will affect the remote machiens as well.
Any ideas welcome - thank you for your help!
After some more research I'm now quite sure that this won't work, but of course feel free to prove me wrong!
To load the environment in bash I have to switch to a bash shell. Even if that is possible "in the background", i.e. without getting a prompt, it would still break any tcsh commands which would then be attempted to execute under bash.
Hmmmm, back to the drawing board...
If $command is set there are arguments to csh, so it is a remote shell command. This works for me in .cshrc:
if ($?command) then
echo Executing non-interactive command in bash: $command $*
exec /bin/bash -c "${command} $*"
endif
echo Interactive bash shell
exec bash -l
Test:
$ ssh remotehost set | grep BASH
BASH=/bin/bash
...
proves that it ran in Bash.
Related
I want to write a script for Ubuntu, which open a terminal-emulator, which only allows users interact with it only once. After finish running user's first command typed in, the terminal close on itself automatically, which is kind of like Win+R on windows OS.
How should I do that?
I try script like gnome-terminal -- bash -c "read cmd && $cmd", but there's two problem:
No auto-complete on user inputting commands;
Commands from .bashrc, .bash_aliases are not recognized.
You can try :
gnome-terminal -- bash --rcfile <(cat ~/.bashrc; echo 'PROMPT_COMMAND="PROMPT_COMMAND=exit"')
I don't have Ubuntu to test at the moment, but bash ... part worked.
We have a script that is executed by httpd as the default ec2-user. However when executed the script does not see any of the environmental variables for that user
the variable is set under user ec2-user
myUseVarHome=/home/ec2-user
myScript.sh
#!/bin/bash
myFolder="${myUseVarHome}/test/www"
USER=$(whoami)
echo "Content-type: text/html"
echo ""
echo "hello $USER"
echo "myFolder=$myFolder"
executing script as ec2-user outputs
hello ec2-user
myFolder=/home/ec2-user/test/www
We then set httpd 2.4 conf
<IfModule unixd_module>
User ec2-user
Group ec2-user
</IfModule>
now call the script with
wget 127.0.0.1/myScript.sh
outputs
hello ec2-user
myFolder=/test/www
The output validates the httpd user is ec2-user, same as manually executing the script, however the env variable ${myUseVarHome} is blank or does not exist.
Is this expected behaviour or do we need to call the env variable another way when executed as httpd user?
bash acts differently whether it is a shell or a normal progamming language (like perl or python).
By designed, those settings in ~/.bash_profile, ~/.bashrc, etc. are for users to set things when bash plays the roll of a shell (login shell, interractive shell). Think about environment you have in a xterm (interractive shell) or in ssh sessions (login shell) or in consoles (login shell).
In other hand, bash is also a powerfull progamming language --think about many scripts for managing services in systemd-- which requires a different style of working. Example, when a developer write a system script or a bash program, he/she will not likely to source user defined ~/.bash_profile automatically. It is a normal program, not a shell. A normal program (including bash programs) would naturally inherrit setting in a current working evironement (shell), but not set them.
If we write a program for cron in bash --it is just happenly it is written in bash; in fact, we can write it in python or perl or any other progamming language-- then, we can have an option to sources bash's ~/.bash_profile (read: setting of user's shell, which happenly to be the same language of your programming language):
[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile
However, what if that particular user do not use bash as his/her shell? He/she may use zsh, 'ksh,fish`, etc. So, that's practice does not really work when writing program for public use.
So, you can source ~/.bash_profile if you think it work. But, here, it is not about whether we are able to source a file, it is about how things should works in the system: the design concept. In short: we should view bash as something having 2 rolls: shell and progamming language. Then everything will be clear, easier to understand.
See: How to change cron shell sh to bash
I used to work with UNIX a couple years ago, and I am just starting to get back into it again. I was wondering if anyone could help me with a question.
For example, if I am in bash, I say chsh --shell /bin/tcsh after this I am prompted to enter my password. If I try to say echo $SHELL it will not tell me I have changed shells. It still tells me I am in bash, not C shell. So I have to exit and restart. Once I log back it, then it tells I am in C shell.
Is there a more effective method to change shells? One that does not require me having to log in and out?
Thank you in advance.
chsh(1): change your login shell
Once you change your shell with chsh, it should automatically login to that shell every time you open a terminal.
If you want to use a different shell temporary, just run that shell directly: "tcsh", "zsh", etc..
If you want to use a particular shell for a script use shebang "#!".
Example -- The following on the first line of a shell script will ensure the script is run with sh (and you can do this for any shell available on your system):
#!/bin/sh
Always check your current shell by using :
echo $0
That way you will get the exact process ( your current shell ) you are running. If you print $SHELL it will return to you the default shell that will be open when you login to the server which unless that's what you need its not reliable.
ubuntu$ echo $SHELL
/bin/bash
ubuntu$ echo $0
-bash
ubuntu$ sh
\[\e[31m\]\u\[\e[m\]$ echo $SHELL
/bin/bash
\[\e[31m\]\u\[\e[m\]$ echo $0
sh
\[\e[31m\]\u\[\e[m\]$
Regards!
My default shell is bash. I have set some environment variables in my .bashrc file.
I installed a program which use .cshrc file. It contains the path to several cshell scripts.
When I run the following commands in the shell windows it works perfectly :
exec csh
source .cshrc
exec bash
I have tried to put these commands in bash script, unfortunately it didn't work.
is there another way to write a script in order to get the same result as running commands from a shell windows.
I hope my question is now clear
Many thanks for any help
WARNING : don't put the following script in your .bashrc, it will reload bash and so reload .bashrc again and again (stopable with C-c anyway)
Use preferable this script in your kit/CDS stuff startup script. (cadence presumably)
WARNING 2 : if anything in your file2source fails, the whole 'trick' stops.
Call this script : cshWrapper.csh
#! /bin/csh
# to launch using
# exec cshWrapper.csh file2source.sh
source $1
exec $SHELL -i
and launch it using
exec ./cshWrapper.csh file2source.sh
it will : launch csh, source your file and came back to the same parrent bash shell
Example :
$> ps
PID TTY TIME CMD
7065 pts/0 00:00:02 bash
$>exec ./cshWrapper.csh toggle.csh
file sourced
1
$> echo $$
7065
where in my case i use the file toggle.csh
#! /bin/csh
# source ./toggle.csh
if ! $?TOGGLE then
setenv TOGGLE 0
endif
if ($?TOGGLE) then
echo 'file sourced'
if ($TOGGLE == 0) then
setenv TOGGLE 1
else
setenv TOGGLE 0
endif
endif
echo $TOGGLE
Hope it helps
New proposal, since I faced another problem with exec.
exec kills whatever remains in the script, except if you force a fork by using a pipe after it `exec script |cat'. In such case if you have environment variable in the script, they are not spread back to the script itself, which is not what we want. The only solution I found is to use 3 files (let's call them for the example : main.bash that call first.cshrc and second.sh).
#! /bin/bash
#_main.bash_
exec /bin/csh -c "source /path_to_file/cshrc; exec /bin/bash -i -c /path_to_file/second.sh"
# after exec nothing remains (like Attila the Hun)
# the rest of the script is in 'second.sh'
With that manner, i can launch in a single script call, an old cshrc design kit, and still process some bash command after, and finally launch the main program in bash (let say virtuoso)
I'm using this bash script:
for a in `sort -u $HADOOP_HOME/conf/slaves`; do
rsync -e ssh -a "${HADOOP_HOME}/conf" ${a}:"${HADOOP_HOME}"
done
for a in `sort -u $HBASE_HOME/conf/regionservers`; do
rsync -e ssh -a "${HBASE_HOME}/conf" ${a}:"${HBASE_HOME}"
done
When I call this script directly from shell, there are no problems and it works fine. But when I call this script from another script, although the script does its job, I get this message at the end:
sort: open failed: /conf/slaves: No such file or directory
sort: open failed: /conf/regionservers: No such file or directory
I have set $HADOOP_HOME and $HBASE_HOME in /etc/profile and the script does the job right. But I don't understand why it gives this message in the end.
Are you sure it's doing it right? When you call this script from the shell it is acting as an interactive shell which reads and sources /etc/profile and ~/.bash_profile if it exists. When you call it from another script it is running as non-interactive and wont source those files. If you want a non-interactive shell to source a file you can do this by setting the BASH_ENV environment variable.
#!/bin/bash
export BASH_ENV=/etc/profile
./call/to/your/HADOOP/script.sh
Everything points to those variables not being defined when your script runs.
You should ensure that they are set for your script. Before the first loop, place the line:
echo "[${HADOOP_HOME}] [${HBASE_HOME}]"
and make sure that doesn't output "[] []" (or even one "[]").
Additionally, put a set +x line at the top of the script - this will output lines before executing them and you can see what's being done.
Keep in mind that some shells don't pass on environment variables to subshells unless you explicitly export them (setting them is not enough).