-1

I want to make a script for a workspace configuration, and I need it to open a ssh terminal, and inside it I need to throw a bash command (because default is tcsh) and over bash, throw another commands, and I want the terminal to stay in the last state.

I have this in the script:

...
cd xxx/xxx
bash
source setup.sh
...
exit 0

and when the script is over, my terminal stays in bash, but didn't execute the next steps.

I also tried this:

ssh -X URL << '___' 
   cd xxx/xxx
   bash -c "source setup.sh"
___

If I launch bash -c only, inside the ssh URL, it works, but if I do it complete, it ends the execution and drops me outside the ssh URL. If I do bash -i at the end it says "bash: no job control in this shell" and dumps me out. The -exec option does the same.

How can I do this correctly?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
carlitox1
  • 33
  • 5
  • Possible duplicate of http://stackoverflow.com/questions/37586811/pass-commands-as-input-to-another-command-su-ssh-sh-etc/37586820#37586820 – tripleee Jun 02 '16 at 08:51

4 Answers4

2

You can pass an arbitrarily complex script to bash on standard input.

bash <<'____'
    source setup.sh
    : things
    # no explicit exit really needed
____
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • This is closer to what i need, but i need the terminal to stay in the last state of the script, in the "source setup". And with this complex script, the everything is executed correctly but it ends pointing to the same place where i started. I tried to run the script with "source" and without the exit 0 at the end and it didn't work either. – carlitox1 Jun 03 '16 at 07:02
  • I'm not sure what you are asking here. Do you want `read -p "done"` at the end of the script so you can see what it did, or do you genuinely need to interact with the shell? Would starting a second interactive shell after executing the scripted commands be acceptable? – tripleee Jun 03 '16 at 07:20
  • See also e.g. http://serverfault.com/questions/368054/run-an-interactive-bash-subshell-with-initial-commands-without-returning-to-the – tripleee Jun 03 '16 at 07:21
  • I need the shell to stay in the last command i made... for example, if my last command is a "cd xxx/yyy", then i need the shell to be pointing to xxx/yyy (and of course, all the previous changes to be subscribed). And that is not happening... The script executes everything correctly, but when it is finished, it points to the "status" where i was previous to launching the script. Neither removing "exit 0" or executing the script with "source" solves this. – carlitox1 Jun 03 '16 at 10:14
  • But running `bash -i` instead of `exit` (or as in the linked question, `exec bash`) or `bash --init-file <(echo some commands)` would work, to the best of my understanding. – tripleee Jun 03 '16 at 10:29
  • No, bash -i and exec bash is not working. Look at my edition of the post please. – carlitox1 Jun 06 '16 at 07:31
  • You need to add an `ssh` flag to allow the commands access to the terminal. On OpenSSH, it's `ssh -t` or `ssh -t -t` to really force it. This is an `ssh` problem, not a `bash` problem (but thanks for finally including this detail in your question). – tripleee Jun 06 '16 at 07:34
  • The commands are actually working in the ssh tunnel, the problem is that when the script terminates, it dumps me out of the ssh tunnel. – carlitox1 Jun 07 '16 at 06:41
  • You tried `ssh -t -t` and it didn't work, or what? There is no tunnel here. Do you have additional requirements which you are not revealing? See also [mcve]. – tripleee Jun 07 '16 at 06:43
  • Maybe accept one of the answers here and post a new, properly scoped question with all the pertinent details. Perhaps include a [link here](/questions/37585884/throw-commands-inside-invoked-terminal-in-bash-script/37587134?noredirect=1#comment62822144_37587134). – tripleee Jun 07 '16 at 06:47
  • The -t -t option leaves the bash damaged; when i write any command inside, it doesn't work. That's why its not working either. The -t option does the same as if i don't use it. My script have exactly what i wrote in my last question (Also tryed all the options you people told me) and any of them is working. that's why i can't mark any answer as correct, sorry :S. The best answer is yours by using the "here" commands, it solves the first bash problem, but its not solving the "and i want the terminal to stay in the last state." that i asked in my first question. – carlitox1 Jun 07 '16 at 09:15
  • If you use a here document, there is no way for Bash to have a sane line discipline. You can enter some commands, but interactive editing of your commands works poorly, for example. The solution to that is to not use a here document. `ssh -t -t user@host 'bash --init-file <(echo "source $HOME/.bashrc; echo \"moo\";")'` works for me. – tripleee Jun 07 '16 at 10:25
  • Not running Bash interactively is a crucial detail which was not included in your original question, and which still is documented only in passing. My advice is still to accept the answer which best answers your *original* question, as stated, not necessarily which solves your actual problem, since you didn't describe it *in your question*. – tripleee Jun 07 '16 at 10:25
0

What I would do is put the commands that would be between your bash line and the exit 0 into a separate file e.g. mycommands.sh

#!/bin/bash
source setup.sh
...
exit 0

chmod +x mycommands.sh

and then invode mycommands.sh at the point where you write bash

But you could also

bash -c "source setup.sh;    ... ;   exit 0"
Stefan Hegny
  • 2,107
  • 4
  • 23
  • 26
  • This could be a solution... but has the same problem that i told to tripleee, and also i don't want to have a script file for every "tunnel" i have to make (i think it is not necesary) – carlitox1 Jun 03 '16 at 07:05
  • but the lower alternative of my two? It ends up having all inside your script (like triplee's solution) and in contrast to your suggestion both are more likely to work. It depends a bit how many commands you intend to put there, if there are only some, maybe bash -c is feasible, if it's a long stuff, the redirect from triplee surely is more elegant – Stefan Hegny Jun 03 '16 at 07:38
  • I see, now I read all the comment at triplee's , sorry did not quite get the point... – Stefan Hegny Jun 03 '16 at 07:48
0

Put "#!/bin/bash" on the header of "setup.sh".

This will make that script run under a Bash shell.

0

Taking a step back & building to a final answer (fwiw the question as stated seems unnecessarily complicated due to artificial, albeit extremely common, administrative/managerial restrictions, so perhaps reframing the question might provide easier work-arounds):

First, you can change your default shell on the remote host (without root) by using chsh -s /bin/bash (or whatever your path to your preferred bash is, eg /opt/local/bin/bash) and put your start-up commands in ~/.bash_login or ~/.bashrc as appropriate (google the precedence rules, but caveat: you may see different behavior across versions of bash + OS, so do test; maybe it's less of an issue today, but in particuar, macOS and older Unix (Solaris) have caused problems for me in the past.) If you actually have root access, just use usermod to change your default shell on the remote (but if this is the case, the question doesn't make sense.)

Along those same lines, to ssh into the remote and start an interactive bash session, using bash -l will cause the init scripts to run for a login shell (eg ~/.bash_login, ~/.bash_profile, ~/.bashrc, again, check the rules for precedence, defaults & fallbacks.) Specifically,

$ ssh -t user@host '/path/to/foo.sh; bash -l'

But note that any commands causing env changes before bash -l won't be in your shell. Not unless they're in the remote init files (~/.bashrc, etc).

So, finally, instead of running the default init files on the remote, you can specify the init file in the bash command, in order to set up your remote env, have those changes stay in your bash shell:

$ ssh -t user@host 'bash --init-file ~/my_env.sh'

where ~/my_env.sh replaces your ~/.bashrc (or whatever). If you also want the ~/.bashrc to run, just "include" (aka "source") it inside your my_env.sh file (ie: . ~/.bashrc).

Lastly, if the ~/my_env.sh file isn't actually physically on the remote, you can pass arbitrary commands via process substitution (to "generate" the init file dynamically):

$ ssh -t user@host 'bash --init-file <(echo "export FOO=bar; source /path/foo.env")'

However, as the syntax <( commands ) is specific to bash, you'll need to either use the comparable syntax in the default remote shell, or run that command in bash (presents an interesting problem in escaping quotes):

$ ssh -t user@host 'bash -c "bash --init-file <(echo \"export FOO=bar; source /path/foo.env\")"'

At this point, you're logged into the remote, a remote bash shell is running, and FOO should be bar, and the remote /path/foo.env will still be in effect in the current shell. (Optionally source your remote ~/.bashrc, but careful about weird things that may not work, eg fancy prompt PS1 stuff, but I digress.)

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
michael
  • 9,161
  • 2
  • 52
  • 49