2015-06-18 7 views
7

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> 
+0

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

+1

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

+0

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

risposta

1

riparato.

  1. L'utente Tom non può accedere alla cartella C:\Stackoverflow per impostazione predefinita, in modo che nulla a correre, ho dovuto dare l'accesso a tutti di leggere/eseguire le voci in quella cartella, altrimenti l'avvio processo fallito miseramente

  2. Aggiungi percorso profilo al comando net user. Ciò ha impedito le cartelle in più in fase di creazione che ho citato in un commento:

    net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /profilepath:C:\Users\Tom /y

  3. sostituire la linea Start-Process con:

    Start-Process C:\stackoverflow\whoami.bat -WorkingDirectory C:\Users\Tom -Credential ($credentials) -Wait

Perché?

Con la directory di lavoro impostata su C: \ StackOverflow, l'interprete dei comandi che sta eseguendo il file batch trova whoami.bat prima del builtin e si verificano tutti i tipi di interruzioni. Una volta che ho spostato la directory di lavoro nella cartella di Tom, tutto ha funzionato esattamente come si voleva.

Alternativa:

Non un nome al file batch lo stesso di comandi incorporati.

+0

Molte grazie Eris per il tempo che hai dedicato a esaminare la mia domanda. Sfortunatamente penso che non abbia ancora risposto per me. Mi scuso, premo invio troppo presto! Lasciami continuare ... –

+0

Le modifiche suggerite non hanno portato al programma go che genera i tre file. Anche lo script di PowerShell ha funzionato quando chiamato dal file demo.bat, quindi la modifica (1) per l'account utente non può essere necessaria. Change (2) è utile, ma non correlato al problema descritto. Il cambiamento (3) non ha avuto alcun impatto per me, e anche nel file demo.bat la directory di lavoro è C: \ stackoverflow, quindi equivalente al programma go, quindi non spiega la discrepanza. Grazie molto. –

+0

Lo script go viene eseguito come utente amministratore, lo script PowerShell viene eseguito come utente amministratore. Solo il file batch viene eseguito utilizzando 'Start-Process' come nuovo utente. – Eris