Shell script using with tmux fails on zsh - bash

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

Related

Why tmux fails to run a bash script when using a bind-key

The script using the normal command ./<script.sh> in a terminal window works without any problem. It troughs error returned 127 when running a bash script with bind-key:
tmux version 3.3a
bind-key -r i run-shell "tmux neww \<script path\>"
I have also tried the run the script from tmux command prompt using the :shell-run 'path/script/script.sh command it still does nothing.
Could someone explain what could be the issue. I was wondering if it could be related to tmux's default sh shell. The script uses #!/usr/bin/bash and not #!/usr/bin/sh.
The run:shell command still fails when I the script to #!/usr/bin/sh

Sending Bash Aliases to detached screen sessions

I'm on a Linux machine using screen, and I'm attempting to write a (fairly portable) function which runs a bash function in a new, detached screen session which automatically closes upon completion. I've had some success, but I noticed the following behavior:
If I include the definition of mail_submit() in my ~/.bashrc file, I can run
mail_submit foo
in the terminal, and also I can access the alias in a new screen session:
screen -S test
mail_submit foo
However, the following command does not work:
screen -d -m -S test sh -c 'mail_submit foo'
presumably because sh -c starts a fresh shell that has no knowledge of my ~/.bashrc profile. So, I can use the following fix:
screen -d -m -S test sh -c 'source ~/.bashrc; mail_submit foo'
which does work.
But if I want to wrap this functionality up into a bash alias (which is my ultimate goal here), this will cause a weird self-referential situation.
Question: What is an easy way to either have sh -c know the location of my ~/.bashrc profile, or use a variant of sourcing the file and creating an alias?
EDIT: I could save the shell script in my home directory, and create an alias which runs
screen -d -m -S test bash -c '~/mail_submit.sh $1'
but I'd still be curious to hear other possible fixes.
A default ~/.bashrc contains this ([[ "$-" != *i* ]] && return) little piece of code on top of it (or somewhere else in the upper part). This line will prevent the ~/.bashrc from beeing sourced if the bash shell doesn't run in interactive mode.
You could:
Remove this line
Create a new file which will only contain the alias you need and source that
Create a little bash script instead of an alias and run that
Do you mean screen -d -m -S test bash -c 'mail_submit foo'?
It looks like you're trying to run the command with the shell (sh), and not the bourne again shell (bash), which is the shell interpreter which actually reads the ~/.bashrc profile.
Edit: The .bashrc file is not being sourced by default because screen does not create the bash process as a login shell, which is when the .bashrc file is read. Creating a .screenrc file with the line defshell -bash will create the bash process as a login shell instead, which will then call the .bashrc file.

ssh and chroot followed by cd in shell

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.

sh: ...: is not an identifier when trying to invoke shell scripts using plink

Below is my shell script that I am trying to execute using PLINK on MachineB from MachineA(Windows Machine).
#!/bin/bash
export HIVE_OPTS="$HIVE_OPTS -hiveconf mapred.job.queue.name=hdmi-technology"
hive -S -e 'SELECT count(*) from testingtable1' > attachment22.txt
I am using plink to execute the shell script like below,
C:\PLINK>plink uname#MachineB -m test.sh
Using keyboard-interactive authentication.
Password:
Using keyboard-interactive authentication.
Your Kerberos password will expire in 73 days.
And this is the below error I always get whenever I try to run like above.
sh: HIVE_OPTS= -hiveconf mapred.job.queue.name=hdmi-technology: is not
an identifier
Something wrong with my shell script? or some trailing spaces? I am not able to figure it out. I am running PLINK from windows machine
The sh: prefix on the error message indicates that the script is being executed by sh, not bash.
bash lets you combine setting a variable and exporting it into a single command:
export foo=bar
sh, or at least some older versions of it, require these two actions to be separated:
foo=bar ; export foo
A version of sh that doesn't recognize the export foo=bar syntax will interpret the string foo=bar as a variable name (and an illegal one, since it isn't an identifier).
Either arrange for the script to be executed by bash, or change this:
export HIVE_OPTS="$HIVE_OPTS -hiveconf mapred.job.queue.name=hdmi-technology"
to this:
HIVE_OPTS="$HIVE_OPTS -hiveconf mapred.job.queue.name=hdmi-technology"
export HIVE_OPTS
For that matter, since you're referring to $HIVE_OPTS at the very beginning of your script, it's almost certainly already exported, so you could just drop the export.
(You'll also need to avoid any other bash-specific features.)
So why is the system invoking the shell with sh? The #!/bin/bash syntax is specific to Unix-like systems. Windows generally decides how to execute a script based on the file extension; apparently your system is configured to invoke *.sh files using sh. (You could configure your system, using Folder Options, to invoke *.sh files using bash, but that might introduce other problems.)
I think the -m option to plink is for reading commands to execute on the remote machine from a local file. If my comment about line endings doesn't work, try
plink uname#MachineB test.sh
Make sure test.sh is executable by running
chmod +x test.sh
on MachineB.

How to force ssh to execute bash instead of the user default on the remote machine?

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.

Resources