Unable to run an interactive shell script using conda run - bash

I have this script "/home/prod/test.sh"
#!/bin/bash
echo Hello, who am I talking to?
read varname
echo It\'s nice to meet you $varname
I was expecting that when I run this command
conda run -n myenv /home/prod/test.sh
I will see a prompt waiting for me to enter the value for varname , instead I got
(base) prod#dev-box:~$ conda run -n reportz /home/prod/test.sh
Hello, who am I talking to?
It's nice to meet you
(base) prod#dev-box:~$
Would very much appreciate a response detailing, how I can use conda to run an inetractive shell script ?
[Edit]
Replaced read varname with read -r varname < /dev/tty
It did wait for my input, but without displaying the output resulting from the echo statement echo Hello, who am I talking to?
Solution I'm looking for - the script should run with conda run command exactly as it would in a typical shell env.

The conda run command defaults to buffering I/O. To have interaction, one needs to include the --no-capture-output flag.
conda run -n myenv --no-capture-output /home/prod/test.sh
This feature was introduced in Conda v4.9.0 (Change Log).

Related

How can I pass command line arguments when activating a conda environment in a shell script

I am on Linux, Python 3.6.
I have a shell script that looks like this:
#!/bin/bash
instance=$1
export instance
echo "Instance is" $instance
. /home/xyz/setenvvars.sh
source activate myenv
echo arg1 $1
echo env $instance
python myprg.py $1
python myprg.py $instance
It seems after I activate the conda environment, the command line argument this shell script received is not available in the activated environment. How can I pass the command line argument this script originally received to newly activated environment. The 2 echos after the activate show blanks.
TIA!

How to record shell interaction from a background script

I want to write a background sh (it can be python or any other language actually) script very much like script.
Its main purpose is to run on the background after invoked and listen to inputs (not the outputs nor the PS1 shell prompt string nor keystrokes like "End", "Ctrl", arrow-keys, etc.) that the user enters to the shell from which the script was originally invoked and then record them.
The dumbest approach would use script and then try to subtract PS1 and outputs from the generated file. But this would be error-prone and there sure are better ways to do this.
I've read about pam_tty_audit but I'm not sure if one can easily filter out just the user input and I'm afraid it won't work for all Linux distributions.
What else can I look into to accomplish that?
A quick example illustrating what I seek:
The user would input this to the shell:
$ ./myscript
MyScript started in the background
$ echo "foo"
$ sudo apt install netcat
[sudo] password for user: MYPASSWORD
...
Do you want to continue? [Y/n] NO
...
$ exit
MyScript exited
And my script would render this output file:
#!/bin/bash
eval "echo \"foo\""
echo "NO" | echo "MYPASSWORD" | eval "sudo apt install netcat"
Obs.: Capturing the password typed for sudo is not really something I would like to perform, the above example is just the first which came to mind.

Effective Methods of changing Shells in UNIX

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!

Run source in bash execution

Quick run down of what I'm doing, I'm making python development environments on my computer using virtualenv. I'm not one to remember all these commands, so I like to build simple(noob-ish) script that will help me.
Problem
As you see on step 2 in the Basic Usage section of the documentation. I need to run a command:
$ source venv/bin/activate
This activates my python environment. So I've tried a mixture of functions and eval. As mentioned, I am a bit of a noob when it comes to bash scripts.
My Code
File: fpyenv
#!/bin/bash
# $ cd ~/scripts/
# $ chmod u+x <filename>.sh
activateSrc(){
eval '$(source "${1}"/bin/activate)'
}
if [[ $1 == '' ]];
then
printf "ERROR: Missing Filename\n"
else
printf "Creating Virtual Environment $1\n"
# This creates the environment
virtualenv $1
printf "Do you want to activate $1 as your virtual environment?(y/n)\n"
# Get answer from user
read answer
if [[ $answer != 'y' ]];
# Said No
then
printf "Did not set $1 as your virtual environment\n"
else
# Said Yes
activateSrc $1
printf "Set $1 as your virtual environment\n"
fi
fi
This is what it should look like:
Step 1
myComputer $ fpyenv venv
returns
Creating Virtual Environment venv
Do you want to activate venv as your virtual environment?(y/n)
Step 2(user inputs y/n)
y
returns
Set venv as your virtual environment
(venv)myComputer $
But what I'm getting is:
Set venv as your virtual environment
myComputer $
So it doesn't run the source venv/bin/activate. Does anyone know what I'm doing wrong? I've looked through many answers, but given that source is commonly used in a different way in bash scripts, the answers I'm getting are no help. Thank you in advance!
FIX:
Change activateSrc to:
activateSrc(){
source $1/bin/activate
}
And execute script like this:
myComputer $ . fpyenv venv
It runs source just as written. The thing is that you need to source this new script as well, otherwise it just runs in a subshell and any changes made by the sourced script are lost when the subshell exits.

source .bashrc from .cshrc

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.

Resources