This question already has answers here:
How to stop a PowerShell script on the first error?
(11 answers)
Closed 3 years ago.
I've been using Unix for about 20 years, but only started using Powershell recently. I have a ps1 script that does a number of tasks.
I know I could check each of them, and throw if they error, but it would be good for the entire script just to exit on any errors - like set -e does in bash.
How can I make a Powershell script exit immediately upon any error?
Using pwsh 6.2.1.
Having just found the answer to my own question:
ErrorActionPreference does this.
$ErrorActionPreference='Stop'
at the top of the ps1 file.
This question already has answers here:
How do I set an environment variable in Perl?
(5 answers)
Closed 6 years ago.
I was trying to set shell variable name with help of perl script.
But it was not running fine.
system("variable_name=\"variable_value\"");
`variable_name=\"variable_value\"`;
Any one tell me why it was not working.
Actually my question was little bit different.
I want to know how to set environment "setenv" with help of perl script.
I have tried
$ENV{"VARIABLE_NAME"} = "home\/path_1\/path_2\/path_3";
Then I fire command echo $VARIABLE_NAME then it is not giving me path that I set from perl script.
Thanks
You have no need to run a new shell to set an environment variable; indeed, doing so is counterproductive, since the value doesn't outlive the shell in which it's assigned (except through any surviving children of that shell which may have inherited the value).
You can simply set an environment variable directly in your perl:
$ENV{"variable_name"} = "variable_value"
Any subsequent shell you start from your perl script will see this.
It was working. The problem is that the next system command runs a new shell which doesn't know about variables set in the first shell.
system 'x=value; echo $x'; # Outputs "value".
system 'echo $x'; # Empty line - the shell with $x doesn't exist anymore.
This question already has answers here:
Is there a way to programmatically set the ApartmentState to STA?
(2 answers)
Closed 7 years ago.
I have a script that needs to run in single-threaded mode, and I currently start it up with the -sta parameter with a batch. Is it possible to run the script in -sta mode only executing the Script? I thought about moving the whole script into one function and execute this function in single-threaded mode.
Is that possible? I don't want to give out a batch file and my ps1.
I think if you were to get PowerGUI and put the script into this, you would be able to package the PS1 file into an exe file which can just be executed like a normal program.
Once PowerGUI is installed you can do this from Tools, Complile Script.
I know that if you want to run a program in the background from a unix command line, you simply add & to the end of the command, but is there an equivalent in windows in order to run something in the background?
A low-budget way of doing this is:
start /min some.exe
This starts the program in a minimised console window, and doesn't wait for the second program to finish.
You can:
Use Windows Scheduler.
Run the exe as a Windows service.
I don't really know of a way to manually start something and have it run in the background like you can do in Unix.
Although not a definitive answer to your question there was a similar question on serverfault here:
https://serverfault.com/questions/121979/tools-to-run-a-background-process-command-line-in-windows
The closest thing in windows to the Linux & is described here from what I can tell:
http://blog.commandlinekungfu.com/2009/04/episode-23-job-control.html
I have a Perl script that contains this code snippet, which calls the system shell to get some files by SFTP and unzip them with WinZip:
# Run script to get files from remote server
system "exec_SFTP.vbs";
# Unzip any files that were retrieved
foreach $zipFile (<*.zip>) {
system "wzunzip $zipFile";
}
Even if some files are retrieved, they are never unzipped, because by the time the files are retrieved and the SFTP connection is closed, the Perl script has already completed the unzip step, with the result that it doesn't find anything to unzip.
My short-term fix is to insert
sleep(60);
before the unzip step, but that assumes that the SFTP connection will finish within 60 seconds, which may sometimes be a gross over-estimate, and other times an under-estimate.
Is there a more sound way to cause Perl to pause until the SFTP connection is closed before proceeding with the unzip step?
Edit: Responders have questioned (and reasonably so) the use of a VB script rather than having Perl do the file transfer. It has to do with security -- the VB script is maintained by others and is authorized to do the SFTP.
Check the code in your *.vbs file. The system function waits for the child process to finish before execution continues. It appears that your *.vbs file is forking a background task to do the FTP and returning immediately.
In a perfect world your script would be rewritten to use Net::SFTP::Foreign and Archive::Extract..
An ugly quick-hackish kind of way might be to create a touch-file before your first system call, alter your sftp-fetching script to delete the file once it is done and have a while like so
while(-e 'touch.file') {
sleep 5;
}
# foreach [...]
Of course, you would need to take care if your .vbs fails and leaves the touchfile undeleted and many other bad side effects. This would be for a quick solution (if none of the other suggestions work) until you get the time to rewrite without system() calls.
You need a way for Perl to wait until the SFTP transfer is done, but as your script is currently written, Perl has no way of knowing this. (It looks like you're combining at least two scripting languages and a (GUI?) SFTP client; this can work, but it's not exactly reliable or robust. Why use VBscript to start the SFTP transfer?)
I can think of four options:
Your Perl script could do the SFTP transfer itself, using something like CPAN's Net::SFTP module, rather than spawning an external job whose status it cannot track.
Your Perl script could spawn a command-line SFTP utility (like PSFTP) that doesn't return until the transfer is done.
Or change exec_SFTP.vbs script to not return until the transfer is done.
If you're currently using a graphical SFTP client and can't switch for whatever reason, I'd recommend using a scripting language like AutoIt instead of Perl. AutoIt has features to wait for windows to change state and so on, so it could more easily monitor for an activity's completion.
Options 1 or 2 would be the most robust and reliable.
The best I can suggest is modifying exec_SFTP.vbs to exit only after the file transfer is complete. system waits for the program it called to complete, so that should solve your problem:
system LIST
system PROGRAM LIST
Does exactly the same thing as "exec LIST", except
that a fork is done first, and the parent process
waits for the child process to complete.
If you can't modify the vbs script to stay alive until it terminates, you may be able to track subprocess creation. If you get subprocess ids, you can monitor them thereby know when the vbs' various offspring terminate.
Win32::Process::Info lets you get a subprocess ids from a running process.
Maybe this is a dumb question, but why not just use the Net::SFTP and Archive::Extract Perl modules to download and unzip the files?
system will not return until the shell it's running the command in has returned; this may be wrong for launching graphical programs and file associations.
See if any of the following help?
system('cscript exec_SFTP.vbs');
use Win32::Process;
use Win32;
Win32::Process::Create(my $proc, 'wscript.exe',
'wscript exec_SFTP.vbs', 0, NORMAL_PRIORITY_CLASS, '.');
$proc->Wait(INFINITE);
Have a look at IPC::Open3
IPC::Open3 - open a process for reading, writing, and error handling using open3()