I would rather copy at least myProgramInputFile (Method 3 alike); I think it would be more robust. There is, however, a way to make it work with the sole Method 1.
My approach
I advise you to make a (local) script that copies the appropriate file to the remote side, triggers execution and cleans afterwards.
We will need three local files: myLocalScript (executable), myRemoteScript and myProgramInputFile.
The content of myLocalScript:
#!/bin/bash
# step 1: storing command line arguments to meaningful names
ssh_command="ssh $1"
script="$2"
input="$3"
# step 2: creating remote temporary file
remote_input=$($ssh_command 'mktemp')
# step 3: copying the content of local input file to the remote temporary file
cat "$input" | $ssh_command "cat > \"$remote_input\""
# step 4: sourcing the script to the remote side
$ssh_command "input=\"$remote_input\" bash -s" < "$script"
# step 5: removing the remote temporary file
$ssh_command "rm \"$remote_input\""
myRemoteScript will look like this:
# shebang is not needed, this script will effectively be sourced
# Do stuff…
myProgram input "$input"
# Do more stuff…
The files myProgramInputFile (local) and myProgram (remote) will stay the way they are in your current setup.
Local usage:
./myLocalScript <username>@<hostname> myRemoteScript myProgramInputFile
Technical notes and explanations:
- In step 2
mktemp creates a file in a temporary directory on the remote machine. We don't want to use mktemp -u to avoid the situation when somebody else actually creates a file with the same name between our step 2 and step 3.
- In step 3 we could use
scp if we used mktemp -u. The remote temporary file already exists so we use cat to write to it.
- In step 4
myRemoteScript needs to know the path to the temporary file in the remote machine context. That's why we pass our local $remote_input as input variable to the remote bash. This way when myRemoteScript is fed to the said bash, the $input in it indicates the temporary file path.
- If we break the remote
bash (say, with single Ctrl + c) then myLocalScript will advance to step 5 and do the cleaning anyway. This is the reason why the cleaning is not at the end of myRemoteScript, although it could be.
Sole Method 1 approach
Thanks to Here Documents you can embed myProgramInputFile into myShellScript.
This will be easy if myProgramInputFile is a text file and myProgram can read stdin (maybe with myProgram input - syntax? or maybe when input is omitted?)
myShellScript will look like this:
# shebang is not needed, this script will effectively be sourced
# Do stuff…
myProgram input - <<"EOF"
The content of myProgramInputFile is pasted here,
it continues here
and here,
and so on.
EOF
# Do more stuff…
Then we will run it as in Method 1:
ssh <username>@<hostname> 'bash -s' < myShellScript
If myProgram cannot read stdin but the remote system allows you to use /proc/self/ then we should write the crucial line in myShellScript like this:
myProgram input /proc/self/fd/0 <<"EOF"
If myProgramInputFile is more than text then we should encode it locally (see uuencode, base64) and decode on the remote side. We should also check if there's no EOF line in the encoded text, change the here document delimiter if so. Note that base64 doesn't use _ so E_O_F is perfectly safe in this case (but maybe not with uuencode, I don't know).
As a proof of concept I gzipped the Super User favicon, encoded it with base64 and embedded in the script. I chose to demonstrate /proc/self/fd/0 approach with cp but it might be cat > ~/SUfavicon.ico as well; or better gzip -cd > ~/SUfavicon.ico earlier in the pipe.
And of course in your case there would be myProgram instead of cp.
Note in this case {} are important, they make the here document be directed to base64 -d.
# shebang is not needed, this script will effectively be sourced
{ base64 -d | gzip -cd | cp /proc/self/fd/0 ~/SUfavicon.ico ; } <<"E_O_F"
H4sICE3cXFkCA2Zhdmljb24uaWNvAO2XT2jTUBzHf2lnO1HXIAiKYHuSIYhzoCgIlV1EdtDDTmMg
CIKI7DQ9Taq71Il0VfBSmP9QmKziYRd3GCoqu40JIhtiB7sIOm1AcJ1r8/y+5bXEZ1KbtH07uMCH
3/pLvvm8lzYvC5FGAdJ1Qo3R+RaivUQUi1mfx9BPodeOns77ZPXXthZy25IgX2bbZkrz5uIjmvz+
lPKCBZAEmkOeH8/ABOjXt1AXb86NUg+Ov/AtSwOoy6gl1PYq+UtuA0RuHjCw32d+Dn6znrzwH/SZ
fy78w6gBr3lkOpH9DPg53nrNLzykVpzjDp8DatFLfrCXArkHlBLzfwcOgUANed4zE320/es4fRDz
7/Zw/XiP3TxHm5bGK9f/mJ/rv5StfP++8sjmxLU/7DWP7FHkiqhfUNuq5J+AM7h/jvDm/F06geOv
AJ5bBX0uwyvnTV5x/2bE/fsGmQK8U6hdTsGhsMXItI3XNq5hPQlbVPZjtRiKgKi1zvDV5bh9ndH/
9jDG/iCi6yuAVaOcXczuYy78ALPgOtjhND/Za/OzBvjtfARb19HP6a3Dr5GHDS4NvJL8g3795GOD
77bkv6rYn97w/9f+Ecl/Q7G/X/K/B0GF/t1gRRpDBoRU+MUYLjusgznR39lsvxjDAFh2GMdPFX4x
hrNOzwQF178NPHNwl8BEk39//Bk06eC9BfY06veH/Z1gFNwHKRAW/pMO8+5p9P2H/Wnp+A7hT0ru
qWasP1X88vqbbpL/FJgBs+AF0FX6PTx/Nvzr6x9W7B+T/BdV+fm7BshL/g6F/ozknq7z/Uur0bsL
PJbcv8ABRe9/Jekz///ntNt4m/z+N+M27xr8qz79n8A90M2fv//6vso+I0QJEF8jYcQNVnAjCiIG
KwYNZgIWtP4uhA2zNQriFRzz/NwwJF5yHzNCGgiy3wHSerE2FQAA
E_O_F
Run it as before:
ssh <username>@<hostname> 'bash -s' < myShellScript
Then you will find ~/SUfavicon.ico on the remote machine.
myShellScriptdoes certain "stuff". Know the pitfalls if you keep using this method.