I am trying to create a rundeck job where I specify the name of a .bat file on a remote server, that I want to execute on that remote server. We don't have an execution node on that server, so I'm using invoke-command to run the job on that (Windows) server. I can run the job fine if I hardcode the file path in the command window.
I'd like to add an option to allow the user to specify the location of the .bat file, to make it easier to create new jobs (we will probably have to create lots of jobs like this).
Right now my workflow is the single command:
Invoke-command -Authentication kerberos -ComputerName <servername> -ScriptBlock{<filename>}
That works, but I cannot figure out how to get the option (${option.prog_run}) to interact with this; either I get a powershell error saying I specified it wrong, or it doesn't actually run anything.
This will "succeed", but doesn't actually run the file:
Invoke-command -Authentication kerberos -ComputerName s12zapap01880 -ScriptBlock{start-process ${option.prog_run} }
This will fail, with an error like so:
16:28:00 At line:1 char:123
16:28:00 + ... <servername>'-ScriptBlock{<filename.bat>' }
16:28:00 + ~
16:28:00 Unexpected token '}' in expression or statement.
That suggests that I'm not escaping the { } correctly, perhaps, but I'm not sure how. What is the proper way to include an option here?
Related
I am currently running a powershell script that displays a message asking which script do you want to run. 1-5?
Once the user selects this it imports credentials using Import-Credential on a clixml file and runs something like:
Invoke-Command -ComputerName $Server -Credential $Cred -ScriptBlock {& C:\Temp\script.ps1}
The script then launches on the server but has no permission to read / copy / move files. I assumed because I ran with the credentials specified it would be able to perform the actions needed.
Troubleshooting
If the credentials specified were wrong then it wouldn't launch the script on the server at all.
I've tried running the script on the server and it works perfectly.
I can't see a way to pass credentials on the
{& C:\Temp\script.ps1} or I would create another set of credentials on the server and use that.
Any help would be appreciated.
I'm trying to run a basic powershell script over ssh, the script is this:
param($passedUrl)
Function Launch-Site($url) {
start chrome $url
}
Launch-Site $passedUrl
When I run this in powershell, in the correct directory, with the command
.\launchSite.ps1 google.co.uk
It runs as expected, it launches google chrome and goes to google.co.uk. However, when I use the same command from my ssh terminal (in the correct directory), it does nothing and gives me no errors as far as I can tell.
The default shell is set to powershell. I can run normal scripts that don't have any parameters passed to them, so I'm thinking this is just some security with windows that isn't letting me pass the parameter. Is there any way to get around/fix this?
For this you will need to use a PowerShell remote session. Something along the lines of:
New-PSSession -HostName HOSTNAME -UserName UserName
Hostname being an IP or FQDN. It will prompt you for a username for authentication. This can be stored also as a variable to pass into the module as well.
So I have a script sitting on a server that I can remote into using Enter-PSSession and run the script from my local environment just fine. What I do is...
Enter-PSSession hostname
cd c:\temp\myscript.ps1
or
$s = New-PSSession -ComputerName hostname
Invoke-Command -Session $s -ScriptBlock {C:\temp\myscript.ps1}
these run the script just fine. The problem I am having is the data is supposed to get sent to a database. If I run the .ps1 on the hostname by RDPing directly into it, it works. If I RDP into the server and go back to my local environment where I Enter-PSSession using the code above, it submits to the database just fine. But when I close out of the RDP session and just try running the script again locally, it doesn't go to the database.
Maybe it is something stupid I am missing but any help would be greatly appreciated.
The important bits are in the myscripts.ps1, so it's impossible to say from what you have provided.
I suggest you check that script file for where the credentials are stored. When you run it locally, I assume you run it from that working directory.
Try using $psexecscript as the root of the config file's path. That's whatever path the script is in, assuming the credentials are in the same or sub- directory.
Is it possible that the user lacks permission to write in your DB or the credentials to write in that DB are not provided in the script?
If after verifying the credential issue, it still doesn't work, you might want to register your script as a task. You can set it as a manual task. Then, whenever you need it, you (remotely) run that task. In that way your credentials are stored as well and you can safely use the 'run as' feature.
This is probably a question with a binary answer.
I have a series of batch files on a server. They all require user input in some way, either via CHOICE or SET.
I would like to run these remotely from my desktop, using powershell.
Is this possible? My tests so far show the batch scripts running, but they skip past any user input.
If the above is not possible, is anyone able to point me to a resource that has information on a powershell implementation of accepting user inputs remotely?
The scripts need to stay in a central location, so all the users should have is a single PS script on their desktop that runs a PS script on the server that is responsible for requesting and handling user input.
Cheers
EDIT:
I tried Invoke-Command and Enter-pssession already, neither work. I get the following error message:
.\MultiScript.bat :
+ CategoryInfo : NotSpecified: (:String) [], RemoteExeption
+ FullyQualifiedErrorId : NativeCommandError
ERROR: The file is either empty or does not contain the valid choices.
Here is a code excerpt:
CHOICE /C 123456789 /M "Enter your choice:"
IF ERRORLEVEL 9 call %installdir%\stream\check1 %input% & GOTO main
...etc
IF ERRORLEVEL 1 call %installdir%\single\getlogs %input% & GOTO main
On my powershell terminal it shows that it is automatically selecting option 9 above to run another script. In the following script, and ID is requested from the user, and I can see there is automatically the female gender symbol (char[9792]) given as input.
The issue really seems to be Powershell does not understand the CHOICE or SET keywords and just skips past them, or gives weird inputs.
You need to invoke the commands remotely. To do this you can use this as an example
Invoke-command -computername SERVERhostname -sessionoption (new-pssessionoption -nomachineprofule) -scriptblock {cmd.exe /c "c:/batchfile.bat -option"}
Replace SERVERhostname appropriately.
Unless you're saying it asks questions. Then you can remote into the server.
Enter-pssession
will do as you need
How can I get a remotely executed script to know it's own location? I'm using Invoke-Command to run a script on a remote server. The script needs to create files in the directory in which it lives. Running with relative addressing doesn't work (i.e. .\output.log), the scripts generally end up in my user profile on the remote server. I tried all the methods outlined in this question but none of them seem to work when the script is remote.
Update: Provided script invocation code per request
$server='ad1hfdahp802'
$remotepath='\\ad1hfdahp802\d$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
$SDFEnvironment='INT'
Invoke-Command -ComputerName $server -FilePath $remotepath -ArgumentList($SDFEnvironment,$remotepath)
The remote script takes the $remotepath and turns it into a file system path.
Using -FilePath with Invoke-Command means that you read the script locally and send the content as the scriptblock to the remote computer. $PSScriptRoot only works when the script is executed directly on the target. You could try using:
Invoke-Command - ComputerName "computer1" -Scriptblock { & '\\server\path\to\script.ps1' } -Authentication Credssp
Be aware that you need CredSSP to make this work since the remote computer can't use your credentials to access network-resources without it. As an alternative, you could use psexec (or start a process remotely). Ex.
psexec \\computer1 powershell -noprofile -file \\server\path\to\script.ps1
After trying some of the changes proposed I've come to understand that the Invoke-Command isn't actually running the remote script at its original location, but rather loading it from the original location and then running it under the context of PowerShell as the user running the local script. The "script directory" is actually a directory in the user's workspace regardless of where the script originally lived.
This clarifies things for me somewhat. While there may be ways to divine where the script originally came from or to actually start a session on the remote server then run the script as a "local" script there, the need for the remote script to further access other servers, creating multiple hops in authentication, means I have to add CredSSP to the mix.
It seems my original plan, to pass the path I'm using to locate the script to the script so it can place output files in the original directory, is probably the best approach given that I also have to add CredSSP to the mix.
I'm open to refutation, but I don't think any of the proposed solutions actually improve the functionality of the remote script so I'm going to stick with what I started with for now. Thanks to everyone for their contributions.
Enter a session on the remote server, and call the script from there.
local PS> Enter-PSSession -ComputerName $server ...
remote PS> powershell d:\AHP\...\script.ps1
remote PS> exit
local PS>
Then you can use $PSScriptRoot in the script in the remote server to get the local path of the directory of the script on the remote server.
EDIT:
To locate the script on the remote server, you can use your knowledge of the network path of the script file, and parse the output of net share to map network path to local path on the remote server.
remote PS> net share | where { $_.StartsWith('D$ ') } | foreach { [regex]::Split($_, " +")[1]}