set env before bash initialization - bash

I am creating new tab to run my command, and kill it when not needed.
$ roxterm --tab -e top
$ pkill -f top
(gnome-terminal is preferred, but doesn't support new tab to execute given command; splitting open & run fails to pkill).
My command requires a setup.sh script setting environment variables to be called prior to execution. However,
$ roxterm --tab -e "source setup.sh; mycommand"
fails, with the error line 1: source not found, as the bash environment is not yet initialized in the just being created roxterm env. How to circumvent.
One option i can think of is to create below script, myscript.sh
source setup.sh
mycommand
but i'd like to avoid creating scripts for each of my commands, and be able to kill it with pkill -f mycommand

Related

How to exec bash script w/o exiting shell

I want to execute a bash script in the current shell, not a subshell/subprocess. I believe using exec allows you to do that.
But if I run:
exec ./my_script.sh
the shell will exit and it will say "process completed". Is there a way to execute a script in the same shell somehow w/o exiting the process.
note the only thing my_script.sh does is:
export foo=bar
but if there was some error in my script, it didn't appear in the console.
As #Snakienn has said, you can / should use the "." builtin command to "source" the file containing commands; e.g.
. ./my_script.sh
What this does is to temporarily change where the shell is reading commands from. Commands and other shell input are read from the file as if they were being read from the terminal. When the shell gets to the end-of-file, it switches back to taking input from the console.
This is called "sourcing". (Not "execing".) And indeed the shell accepts source as an alternative name for the . command.
The exec command does something completely different. As the bash manual entry says:
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the shell. No new process is created. The arguments become the arguments to command.
The concept and terminology of exec comes from early UNIX (i.e Unix V6 or earlier) where the syscalls for running a child command were fork and exec. The procedure was:
fork the current process creating a clone of current process (the child)
in the child process exec the new command
in the parent process, wait for the child process to complete
you can try . ./my_script.sh.
The first dot stands for the current shell.
man page says:-
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the shell. No new process
is created. The arguments become the arguments to command. If
the -l option is supplied, the shell places a dash at the
beginning of the zeroth argument passed to command.This is
what login(1) does. The -c option causes command to be executed
with an empty environment.
if you want to execute a bash script in the current shell,you can try
bash my_script.sh or ./my_script.sh

How can I open shell and then execute a command inside it

What I want is to open default shell, then call another and execute a command there.
Was trying something like this:
c:/Windows/System32/bash.exe -c "zsh & zstyle"
or
cmd /k "c:/Windows/System32/bash.exe -c zsh" & zstyle - this open shell but doesn't run a commands
or
c:/Windows/System32/bash.exe -c "zsh -c 'zstyle'"
Currently I am using a cmder/conemu terminal for windows.
Unfortunately, passing a startup to command to zsh with -c and keeping it open for interactive use (with -i) doesn't work.
Disclaimer: The following solutions were tested from a regular Command Prompt (cmd.exe), not cmder/conemu, though I'd expect them to work there too.
To try them from PowerShell (v3+), insert --% as the first argument after (right after bash.exe).
Here's a workaround:
c:/Windows/System32/bash.exe -c "zsh -c 'zstyle' && exec zsh -i"
Note that command zstyle is executed in a different, transient zsh instance, so this approach won't work for commands whose purpose is to modify the environment of the interactive shell that stays open.
If that is a requirement, things get more complicated (this solution courtesy of this answer):
c:/Windows/System32/bash.exe -c "{ { echo 'zstyle'; echo 'exec 0<&3-';} | zsh -i; } 3<&0"
Note, however, that both commands being executed will be printed before their output, if any, is shown, preceded by the prompt - as if the commands had been typed interactively.

How to source a bash-script within tcl (expect)

I want to set an http proxy within the bash environment (export http_proxy=xyz). So I added the command to the end of the .bash_profile and called
exec /bin/sh -c "source /path/to/.bash_profile"
But it does not work like expected: $::env(http_proxy) does not exist (but there is no typo).
I also tried to run the script like that: exec /bin/sh -c [exec cat /path/to/.bash_profile] .. but with the same result.
Saying
exec /bin/sh -c "source /path/to/.bash_profile"
would source the /path/to/.bash_profile in a subshell. So any changes made to the environment are effectively ignored when the command is done executing.
In order to pass an environment variable to a program, try:
exec /usr/bin/env http_proxy=xyz program

How to source a csh script from inside a bash script

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)

Problem with bash script

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

Resources