Desidero eseguire uno script batch di Windows da go, con un utente diverso per l'utente che esegue il programma go. L'utente che esegue andare ha più privilegi rispetto all'utente che deve eseguire lo script batch.Perché Powershell Start-Process non funziona quando chiamato da go (golang)?
Da go ci sono diverse opzioni per eseguire un processo con un utente diverso su Windows, come scrivere le chiamate di windows direttamente usando il pacchetto syscall in go. Non ho ancora provato questo, ma ho provato sia con PsExec che con Powershell. Powershell è preferito poiché viene installato come standard su Windows 2008 R2.
Il seguente codice dimostra il problema che ho. Nella seguente demo, eseguo uno script batch. Questo script batch chiama direttamente uno script PowerShell, quindi lo chiama da un programma go. I risultati sono diversi. Lo script Powershell emette 3 file, ma quando chiamato da go, emette solo 2 file.
Per motivi di completezza, mostro anche come è stato creato l'utente.
C: \ StackOverflow \ demo.bat:
::::: create a new user for the demo :::::
:: first create a home directory
mkdir C:\Users\Tom
:: remove Users group
icacls C:\Users\Tom /remove:g Users
:: remove Everyone
icacls C:\Users\Tom /remove:g Everyone
:: create user Tom and set his home directory
net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /y
:: Give Tom access to his home directory
icacls C:\Users\Tom /grant:r Tom:(CI)F SYSTEM:(CI)F Administrators:(CI)F
:: give him access to Remote Desktop
net localgroup "Remote Desktop Users" /add Tom
::::: now call powershell directly :::::
powershell -command C:\stackoverflow\demo.ps1
:: show which files were created
dir C:\Users\Tom
:: cleanup
del /f /q C:\Users\Tom\*
::::: run the go version to do the same thing :::::
go run C:\stackoverflow\demo.go
:: compare results
dir C:\Users\Tom
:: cleanup
del /f /s /q C:\Users\Tom
rmdir /s /q C:\Users\Tom
:: delete user
net user Tom /delete
C: \ StackOverflow \ demo.ps1
write-output "test output" | out-file C:\Users\Tom\started.txt
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList @("Tom",(ConvertTo-SecureString -String "_Jerry123_" -AsPlainText -Force))
Start-Process C:\stackoverflow\whoami.bat -WorkingDirectory C:\stackoverflow -Credential ($credentials) -Wait
write-output "test output" | out-file C:\Users\Tom\finished.txt
C: \ StackOverflow \ demo.go
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
run(exec.Command("PowerShell", "-Command", "C:\\stackoverflow\\demo.ps1"))
}
func run(cmd *exec.Cmd) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Start()
if err != nil {
panic(err)
}
err = cmd.Wait()
if err != nil {
panic(err)
}
fmt.Println("Done")
}
C: \ stackoverflow \ whoami.bat:
whoami > C:\Users\Tom\whoami.txt
Ed ora, i risultati - qui si vede quando chiamato da script batch, file started.txt, whoami.txt, finished.txt tutto vengono creati. Quando chiamato da go, vengono creati solo start.txt e finished.txt. Perché?
uscita:
C:\stackoverflow>demo.bat
C:\stackoverflow>mkdir C:\Users\Tom
C:\stackoverflow>icacls C:\Users\Tom /remove:g Users
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files
C:\stackoverflow>icacls C:\Users\Tom /remove:g Everyone
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files
C:\stackoverflow>net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /y
The command completed successfully.
C:\stackoverflow>icacls C:\Users\Tom /grant:r Tom:(CI)F SYSTEM:(CI)F Administrators:(CI)F
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files
C:\stackoverflow>net localgroup "Remote Desktop Users" /add Tom
The command completed successfully.
C:\stackoverflow>powershell -command C:\stackoverflow\demo.ps1
C:\stackoverflow>dir C:\Users\Tom
Volume in drive C is OSDisk
Volume Serial Number is CCD6-C9E7
Directory of C:\Users\Tom
06/18/2015 06:36 AM <DIR> .
06/18/2015 06:36 AM <DIR> ..
06/18/2015 06:36 AM 28 finished.txt
06/18/2015 06:36 AM 28 started.txt
06/18/2015 06:36 AM 55 whoami.txt
3 File(s) 111 bytes
2 Dir(s) 16,489,889,792 bytes free
C:\stackoverflow>del /f /q C:\Users\Tom\*
C:\stackoverflow>go run C:\stackoverflow\demo.go
Done
C:\stackoverflow>dir C:\Users\Tom
Volume in drive C is OSDisk
Volume Serial Number is CCD6-C9E7
Directory of C:\Users\Tom
06/18/2015 06:36 AM <DIR> .
06/18/2015 06:36 AM <DIR> ..
06/18/2015 06:36 AM 28 finished.txt
06/18/2015 06:36 AM 28 started.txt
2 File(s) 56 bytes
2 Dir(s) 16,489,889,792 bytes free
C:\stackoverflow>del /f /s /q C:\Users\Tom
Deleted file - C:\Users\Tom\finished.txt
Deleted file - C:\Users\Tom\started.txt
C:\stackoverflow>rmdir /s /q C:\Users\Tom
C:\stackoverflow>net user Tom /delete
The command completed successfully.
C:\stackoverflow>
Vedo che il contatore "byte liberi" non viene modificato tra i due comandi 'dir', mentre dovrebbe, poiché c'erano tre file nella cartella dopo l'esecuzione di Powershell e due dopo l'esecuzione di Go. Pertanto il file è stato creato, anche se non è visibile (controlla 'attrib -r -h -s c: \ users \ tom \ whoami.txt') o si trova altrove. Cerca i file con il nome contenente 'whoami' dopo aver eseguito il comando go, probabilmente c'è un problema con le autorizzazioni sul file o il reindirizzamento delle cartelle. – Vesper
Grazie Vesper, questa è stata una buona idea. Sfortunatamente non è la ragione; il comando 'attrib' restituiva' File non trovato 'e il file non si presentava in una ricerca. Ho quindi fatto un rapido test e creato alcuni piccoli file, e anche i 'byte liberi 'non sono cambiati quando si esegue' dir' - quindi penso che potrebbe essere una falsa pista. Immagino che 'byte liberi 'non sia sempre aggiornato immediatamente. –
Potrebbe essere che l'ambito di 'go' fa in modo che PowerShell dimentichi che gli script .bat sono associati a' cmd/c', mentre PowerShell invocato all'interno di uno script batch mantiene l'associazione? Fa la differenza se si avvia 'Process-cmd.exe'/c c: \ stackoverflow \ whoami.bat "-otherargs'? In caso contrario, non fa alcuna differenza inserire "set-executionpolicy remotesigned" nella parte superiore di demo.ps1? – rojo