If in shell script I write
chroot /home/mayank/chroot/codebase
cd SBC
when I run this shell script It does go in the chroot but does not execute the command cd SBC,
when I exit chroot then it executes cd SBC.
How can I achieve something that does chroot and execute commands in chroot through shell script ??
When you run chroot without telling it what to do, it will try to start chrooted interactive shell session. So your script would "pause" at that point and when you are done with that interactive shell session, it continues out of chroot again.
One of the quick and dirt options would be to abuse here-document, like this:
chroot /home/mayank/chroot/codebase /bin/bash <<"EOT"
cd /tmp/so
ls -l
echo $$
EOT
Which takes all lines up to EOT and feeds them into bash started through chroot. Those double quotes around "EOT" should ensure bash passes the content not trying to expand variables and such. Hence that echo $$ should be PID of the inner chrooted bash.
somewhat I found a solution,
chroot /work3/tmp_GU/$build_env/sbcbuild/chroot ./test.sh
after chroot giving a script there is working fine for me.
test.sh present in the chroot folder.
All commands in test.sh will be executed in chroot folder.
So basically giving a command after chroot
man chroot
chroot [OPTION] NEWROOT [COMMAND [ARG]...]
Related
According to a document, it says:
When an interactive shell that is not a login shell is started, Bash reads and executes commands from ~/.bashrc, if that file exists.
I did a quick test:
At my server,
[USER#MYSERVER ~]$ cat .bashrc
...
echo 'I am in a bashrc file of my server'
...
At a remote server,
# unquoted
[USER#REMOTESERVER ~]$ ssh MYSERVER echo $-
I am in a bashrc file of my server
himBH
#quoted
[USER#REMOTESERVER ~]$ ssh MYSERVER 'echo $-'
I am in a bashrc file of my server
hBc
When command is unquoted, it seems to be run in an interactive shell, and when quoted, it seems to be run in a non-interactive shell.
Why is this so?
And both read the bashrc file of MYSERVER, which doesn't follow the rule in the document.
Any link or comment appreciated.
EDITED:
And it seems to be a non-login shell.
[USER#REMOTESERVER ~]$ ssh MYSERVER 'shopt -q login_shell && echo 1 || echo 2'
2
In the bash document, there says:
Invoked by remote shell daemon
Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by the remote shell daemon, usually rshd, or the secure shell daemon sshd. If Bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc, if that file exists and is readable.
I missed this part...
Therefore, calling from ssh should read .bashrc file.
And ssh remote command is a non-interactive shell, as comments to the question explain.
The remote bash is indeed not started as an interactive shell (as we can see from the output from $-), so somewhat else must be sourcing your .bashrc. For sure, it is run as a login shell. Could it be that you have a ~/.bash_profile or ~.bash_login or ~/.profile, which explicitly sources .bashrc?
How to excute cd command after chroot to a remote node in shell script?
For ex:
I need this.
ssh remote-node "chroot-path cd command here; extra commands"
Without chroot it works fine, If I put the command list in another shell script and execute the shell script after chroot it seems to run okay.
But chroot seems to break cd?
Use printf %q to have your local shell (which must be bash) give you correct quoting that works, and bash -c to explicitly invoke a remote shell compatible with that quoting (as %q can generate bash-only quoting with input strings that contain special characters) under your chroot.
cmd_str='cd /to/place; extra commands'
remote_command=( bash -c "$cmd_str" )
printf -v remote_command_str '%q ' "${remote_command[#]}"
ssh remote-node "chroot /path/here $remote_command_str"
The bash -c is necessary because cd is a shell construct, and chroot directly exec's its arguments (with no shell) by default.
The printf %q and correct (single-quote) quoting for cmd_str ensures that the command string is executed by the final shell (the bash -c invoked under the chroot), not your local shell, and not by the remote pre-chroot shell.
Assuming by chroot-path you mean chroot /some/root/path.
chroot only takes a single command and cd isn't a command it is a shell built-in so that won't work.
Additionally only cd command here is being run (or attempted to) under the chroot setup. Everything after the ; is running in the main shell.
A script is the easiest way to do what you want.
I try to make a small alias script to automatically reset my OS X Fuse connection.
If I run this command in my terminal:
pgrep sshfs|pbcopy; kill -9 $(pbpaste);echo my_password|pbcopy; sudo
umount path/to/my/mount/folder;
it works perfectly. If I however add it to my .bash_profile as an alias:
alias mount-reset="pgrep sshfs|pbcopy; kill -9 $(pbpaste);echo my_password|pbcopy; sudo umount path/to/my/mount/folder;"
It jumps over the pbpaste command and echoes my_password. I always thought that the alias commands are executed exactly as if I would write them to the terminal, but why is this not working? How do I pbpaste in alias script? What fundamentals have I understood wrong?
You need to wrap the alias in single-quotes, rather than double-quotes. The relevant difference is that bash expands $something (including $(command)) inside double-quotes before executing the command. The way you have it at the moment, pbpaste is executed when .bash_profile runs, and whatever happens to be in the paste buffer at that time gets included in the alias. With single-quotes, it includes $(pbpaste) directly in the alias, so it gets expanded when you use the alias.
alias mount-reset='pgrep sshfs|pbcopy; kill -9 $(pbpaste);echo my_password|pbcopy; sudo umount path/to/my/mount/folder;'
However, there's an easier way. I don't see any reason to pass the sshfs PID through the paste buffer; just use include it directly:
alias mount-reset='kill -9 $(pgrep sshfs);echo my_password|pbcopy; sudo umount path/to/my/mount/folder;'
...but that's still more complicated than it needs to be, because OS X includes a killall command which kills processes by name, thus eliminating the need to pgrep:
alias mount-reset='killall -9 sshfs;echo my_password|pbcopy; sudo umount path/to/my/mount/folder;'
(BTW, some unixes include a command named killall that does something much more dangerous -- this alias is not portable!)
In OS X alias commands should be added to ~/.bashrc
When bash is an interactive non-login shell it uses .bashrc, not .bash_profile. If bash is invoked as an interactive login shell, it uses .bash_profile, not .bashrc.
Try adding the alias to ~/.bashrc. If you wanted to add a mount-reset command as an interactive login shell command into ~/.bash_profile you could use something like this:
# kill sshfs
mount-reset () { pgrep sshfs|pbcopy; kill -9 $(pbpaste); echo my_password|pbcopy;
sudo umount path/to/my/mount/folder; }
I have following script:
#!/usr/bin/env bash
# set -xv
tmux new-window -n 'foo' 'source "$HOME/.rvm/scripts/rvm"; sleep 123' \;
On one machine it works perfectly, on the second I got an error:
sh: 1: source: not found
Ofcourse running command from shell works perfectly.
What is wrong? Machines have similar dot files....
source is not a POSIX command. Use . instead. The machine that fails is probably using dash as the system shell, not bash. The fact that tmux is executed from a bash script does not mean bash is used to execute the command given to new-window. tmux will use the system shell /bin/sh, so the command should not rely on non-POSIX features like the source synonym for ..
I want to execute a bash script with ssh but when I try this it's using ksh which is the user's default shell.
I can't change that default.
So, how can I trick ssh to execute my script with bash instead of the default shell?
Make this the first line of your script:
#!/usr/bin/env bash
Edit: As per this, the utility of /usr/bin/env is dubious. So, you probably want:
#!/bin/bash
Replace /bin/bash with the actual path of bash executable.
You can call your script explicitly with bash:
ssh <ssh-opts> bash <scriptname>
This way there will be a ksh executed at login, but inside ksh you start a bash executing your script.