How to pass a string variable to a command in powershell? - powershell

I intend to use a powershell variable in a script to pass a string value to a command whereupon the command is executed with the parameters as defined in the string. I have been looking at this for a couple of hours now and I don't see what I am doing wrong. I have simplified as much as I can. In the hope of fresh eyes I attach an image, showing:
a. the script that I am using. It's three lines long.
$Parms = "-it amazonlinux2 /bin/sh"
Write-Output "& docker run $Parms"
& docker run $Parms
b. the PS command line where I execute the script.
PS C:\dev\gamelift\serversdk\build> ./test
c. the result of the script's execution
& docker run -it amazonlinux2 /bin/sh
unknown shorthand flag: ' ' in - amazonlinux2 /bin/sh
See 'docker run --help'.
d. the same command executed immediately at the prompt.
PS C:\dev\gamelift\serversdk\build> docker run -it amazonlinux2 /bin/sh
e. the result of the prompt command, which is correct
sh-4.2#
Image of the above
What magic is happening so that the Write-Output is not being interpreted as the command? I have tried:
a. docker run $Parms (without the &)
b. & docker run "$Parms" (in quotes)
c. $Parms = "amazonlinux2 /bin/sh" and & docker run -it $Parms (different error)
d. $Parms = "amazonlinux2" and & docker run -it $Parms /bin/sh (works)
e. escaping the hyphen (different error)
f. $Parms = "-it amazonlinux2 /bin/sh" and each of & docker run $($Parms), & docker run ${$Parms} and & docker run ${Parms}
I'm feeling a bit stupid. I can't see how the Write-Output is right but the call command is bork. It can't be that hard...

The Call operator (&) does not parse strings so "you cannot use command parameters within a string when you use the call operator". You can, however, pass an array so the following will work:
$Parms = "-it amazonlinux2 /bin/sh"
Write-Output "& docker run $Parms"
$myargs = -split $Parms
& docker run $myargs
Alternatively using Invoke-Expression (alias iex) will also do the trick e.g.:
$Parms = "-it amazonlinux2/bin/sh"
Write-Output "& docker run $Parms"
iex "docker run $Parms"

This is a frequently asked question, although not well documented. The call operator parameters work as an array:
$Parms = '-it','amazonlinux2','/bin/sh'
Write-Output "& docker run $Parms"
& docker run $Parms
I would just run docker directly.
docker -it amazonlinux2 /bin/sh

Related

How to parametrize a variable value in shell script?

I am a newbie to writing shell scripts. Please help me in parameterizing a variable value in my shell script.
I am taking command-line arguments for database name, server, user, and password in the following way:
database_name=$1
server=$2
user=$3
password=$4
I want to understand how I can pass these values to a variable called sqlcmd. I pass these values in the following way and then echo to see the value of sqlcmd variable:
sqlcmd=sqlcmd -S $server -U $user -P $password
echo $sqlcmd
after making the shell script executable using chmod a+x on ubuntu. I run the script and get the following error
line 37: -S: command not found. Line 37 in my shell script is a line on which sqlcmd variable is initialized
P.S I am using WSL on a remote windows machine. I am not sure if that should cause an error.
You need quotes:
sqlcmd="sqlcmd -S $server -U $user -P $password"
Note that you may run into difficulties later trying to execute the contents of sqlcmd.

Powershell - Run SCP command using CYGWIN but also expand variables

I need to expand variables before running the SCP command as a result I can't use single quote. If I run the script using double quotes in Powershell ISE it works fine.
But doesn't work if I run the script through command prompt.
I'm using zabbix to run the script which calls the script as [cmd /C "powershell -NoProfile -ExecutionPolicy Bypass -File .\myscript.ps1"]
Here is the code that needs to run SCP using Cygwin bash.
if ((test-path "$zipFile"))
{
C:\cygwin\bin\bash.exe -l "set -x; scp /cygdrive/e/logs/$foldername/dir1/$foldername.zip root#10.10.10.10:~/"
}
Output:
/usr/bin/bash: set -x; /cygdrive/e/logs/myfolder/dir1/server.zip root#10.10.10.10:~/: No such file or directory
If I run the same command above in Cygwin manually it works.
I even tried to use bash -l -c but then the SSH session is stuck maybe because the root#10.10.10.10 becomes $1 according to the documentation.
Documentation link
-c If the -c option is present, then commands are read from
the first non-option argument command_string. If there are
arguments after the command_string, the first argument is
assigned to $0 and any remaining arguments are assigned to
the positional parameters. The assignment to $0 sets the
name of the shell, which is used in warning and error
messages.
Figured it out. It was halting when using bash -c was due to StrictHostKeyChecking, the known hosts thing (where you get a prompt to type yes/no). I set the -v switch to SCP and it showed me the Debug logs where it was halting.
Had to set scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null options.
The complete line now looks like the following:
c:\$cygwin_folder\bin\bash.exe -c ("/usr/bin/scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -v -i /cygdrive/c/cygwin/home/myuser/.ssh/id_rsa /cygdrive/e/logs/$foldername/dir1/$foldername.zip root#10.10.10.10:~/")

Running interactive container with power shell

I'm trying to setup an automated build container in Windows(host and guest). Right now I'm having problems executing a simple powershell inside the container. I've done the following:
Created this DockerFile:
# escape=`
FROM microsoft/windowsservercore
SHELL ["cmd", "/S", "/C"]
CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
Executed this build command:
docker build -t test:latest .
Started the docker with this command:
docker run test
The PowerShell prints this and the container exits:
PS C:\>
D:\repo\docker\Teste
Tried again with this command:
docker start d05ee -ai
The PowerShell prints the same output:
PS C:\>
D:\repo\docker\Teste
I wish to use the container interactively in a first moment to validate the tools I will install on it, but I'm not able to do that. I don't now which error is blocking me to do it and that is my question.
Obs1: The powershell in a windows cmd with the same parameters work fine.
Obs2: I've based my DockerFile on the one in this tutorial.
Obs3: Running this works fine:
docker run -it microsoft/windowsservercore powershell -NoLogo -ExecutionPolicy Bypass
Therefore I presume the problem is on the image generation.
you need to run your container with the -it switch. this will make you container interactive, so you can poke around
docker run -it test

RUN Powershell Script in Docker Container From Host Powershell Script

I have a powershell script in host which copy some files and starts the container.
#Copy File
docker cp "D:\addApplication.ps1" website:/inetpub/wwwroot/
#Start Container
docker start website
Write-Host 'Process has started'
#Execute Container
docker exec -ti website powershell
#Run Script
Invoke-Expression "C:\inetpub\wwwroot\addApplication.ps1"
Second last command executes fine but last command will only execute when I exit the container session and returns error(File Not Found which is because it finds that file on host)
Question: Is there anyway I can execute the command in container session from the script. Or execute any command from script in any process(confused)
Any help is appreciated.
Thanks
Do not use the -ti flags to start an interactive session, just execute the script directly via the docker exec command
docker exec website powershell -command "C:\inetpub\wwwroot\addApplication.ps1"

Can't run commands on other user (su) using Plink in PowerShell

I'm trying to use Plink to connect to a remote UNIX server, su to another user (without password) and finally execute some commands.
$commands = #(
"su - $UNIXUSER;",
"id"
)
echo y | plink -ssh $SERVER -l $USER -pw $PWD $commands
When I execute the code above using PowerShell I get a message saying he was able to change the user, but when I execute the command id he returns the id I logged in in the first place, not the su user.
How can I execute commands using Plink within a su user?
This cannot work.
I'm surprised that you even get the id executed.
The PowerShell effectively executes this.
plink -ssh $SERVER -l $USER -pw $PWD "su - $UNIXUSER;" id
First that's a wrong syntax.
An even it were correct, you can provide only a single command string on plink command line. While you can combine multiple shell commands using ; or & to a simple command string, that cannot work with su. The second command, the ls is not command of the main shell anymore. That's an inner command of the su, i.e. a complete different stream/input/whatever you call it.
What you need to do is to emulate user typing the commands, so that the first command gets processed by the main shell and the second command by the su executed from the main shell. You can do that via an input redirection only.
You can do:
"su - $UNIXUSER`nid`nexit`nexit`n" | plink -ssh $SERVER -l $USER -pw $PWD -T
The -T was added to disable pty allocation (i.e. to get a non-interactive shell), to get the behavior of -m (which implies the -T).
(I do not do PowerShell. There's probably a more elegant way to present the commands than using the string.)