powershell $lastexitcode does not work when running batch files - powershell

I try to get the exitcode/errorlevel code from a bat file into the powershell script calling the bat file.
Althought the %ErrorLevel% is 1:
BAT file
call aCONFIGURATION
for %%f in (.\createData\*.g.sql) do sqlcmd -b -U %UserName% -P %Password% -S %sqlClonedServer% -d %sqlClonedDatabaseName% -i %%f -r1 1> NUL
echo %ERRORLEVEL%
When I do in the powershellscript
$lastexitcode its ALWAYS 0 but the %ErrorLevel% says 1
$build = "c:\my.bat"
$state = & $build
Write-Host $LASTEXITCODE
I am pulling my hairs of this crap powershell full with bugs.
I have read these links but they did not help as the result is different:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/06/06/get-legacy-exit-codes-in-powershell.aspx
https://social.technet.microsoft.com/Forums/scriptcenter/en-US/05e37b8d-761b-4fd7-881e-977f114ad8d7/obtaining-errorlevel-return-codes-in-powershell-is-it-possible
How can I fix the $lastexitcode

echo %ERRORLEVEL% just writes the error code to stdout, after which the batch file exits normally.
If you want the batch script to actually return an error on exit, use exit /b [exitcode]:
call aCONFIGURATION
for %%f in (.\createData\*.g.sql) do sqlcmd -b -U %UserName% -P %Password% -S %sqlClonedServer% -d %sqlClonedDatabaseName% -i %%f -r1 1> NUL
exit /b %ERRORLEVEL%

Related

SSMS agent job using scp command to transfer files to sftp is going to loop and not completing

Have tried different approaches to make the SSMs job working with SCP command with perl script. but the job is going into loop with out having a result.
PS : The script is working fine with running from command prompt directly.
command used in the perl script:-
$Command = "scp -i D:\File1\RS2\DataFeed\Code\PrivateKey.ppk -s $InternalFile admin#sftp.world.com:$VendorName/$DestFileName";
system command used in perl
system($command);
While running the command directly from windows cmd it is correctly placing file to the SFTP. but while running this perl script from ssms agent job it seems not working and the job is keep running without any results.
Any possible leads to the actual errors will be much appreciated
Detailed Steps :
Job in SSMS :
Step :
DataFeed.cmd
%_Debug% echo off
cd /d %0\..
pushd .
setlocal
rem -----------------------------------------------------------------
rem Localize environment
rem -----------------------------------------------------------------
if exist DataFeed_Environment.cmd (
call DataFeed_Environment.cmd
) else (
echo DataFeed_Environment.cmd not found!!!
echo
goto CmdUsage
)
rem -----------------------------------------------------------------
rem Run perl package
rem -----------------------------------------------------------------
C:\Perl\bin\perl.exe DataFeedProd1.pl
if %ERRORLEVEL% NEQ 0 goto ErrorExit
goto Exit
rem -----------------------------------------------------
rem Command Usage
rem -----------------------------------------------------
:CmdUsage
Echo ---------------------------------------------------------------------
echo.
echo DataFeed.cmd
echo Wraps the call to DataFeed.pl,
echo mails log upon errors.
echo.
echo Usage:
echo DataFeed.cmd
echo.
echo ----------------------------------
rem endlocal
rem popd
rem exit 1
rem -----------------------------------------------------------------
rem Error exit
rem -----------------------------------------------------------------
:ErrorExit
echo DataFeedProd1.pl failed !!!
echo
rem endlocal
rem popd
rem exit 1
rem -----------------------------------------------------------------
rem Exit
rem -----------------------------------------------------------------
rem endlocal
rem popd
:Exit
rem exit 0
sub CopyDataFeedFileToSftp{
my ($DataFeedFileInternal, $DataFeedVendorName,$DataFeedFileName) = #_;
my($DestFileName)=$DataFeedFileName.".zip";
my($Command);
my($RetValue) = 1;
$Command = "C:\\Users\\hprasu\\Downloads\\OpenSSH-Win64\\scp.exe -i D:\\File1\\RS2\\DataFeed\\Code\\PrivateKey.ppk -s $DataFeedFileInternal a_Tne\#nasftp\.egencia.com:$DataFeedVendorName/$DestFileName";
$RetVal = &CallSystem($Command);
if ($RetVal == 0) {
&AppendFileToLog($TempFile);
&ErrorExit("Unable to copy data feed file using SCP command:\n".$Command);
}
}
The above perl method is executing the System command
You should:
have full path to perl.exe and your perl script in job's command
escape all special characters in interpolated strings for Perl and
use full path for scp command since
operating system don't know where scp.exe is located (until it in the $PATH):
check filesystem permissions for all files in the command and perl script. Job should has access those files.
So command would be
$Command = "full_path\\scp.exe -i D:\\File1\\RS2\\DataFeed\\Code\\PrivateKey.ppk -s $InternalFile admin\#sftp.world.com:$VendorName/$DestFileName";
Read this:
https://www.geeksforgeeks.org/perl-quoted-interpolated-and-escaped-strings/

How do I configure mongodb to remove old log files?

I've read the mongodb docs and am rotating my log files on Windows 10. However, the number of logs grow until I manually delete them. I'd like to keep 30 days worth of logs.
I was hoping there was a config setting similar to NLog where I can specify how many files to keep before they are re-written. Maybe I am misunderstanding something in the docs. What is the "best practice" for automatically removing old log files?
Looks like the easiest way to do this without 3rd party utilities is to create a batch file that runs each night via Task Scheduler.
years later, but still helpful might be this cmd-script. It's written to remove old stuff in my profile, but really simple to extend:
#echo off
#setlocal
REM Remove everything older then "/D" days (ten/10 days in our examples below)
REM BUT we can not remove directories with files in it, so we do it in two-steps ways:
REM 1st remove all files by using the command: del
REM 2nd remove all files by using the command: rd
REM cleanup %TMP%
forfiles -p "%TMP%" -m * /D -10 /C "cmd /c del /s/q #path > nul 2> nul"
forfiles -p "%TMP%" -m * /D -10 /C "cmd /c rd /s/q #path > nul 2> nul"
REM cleanup %TEMP%
forfiles -p "%TEMP%" -m * /D -10 /C "cmd /c del /s/q #path > nul 2> nul"
forfiles -p "%TEMP%" -m * /D -10 /C "cmd /c rd /s/q #path > nul 2> nul"
REM cleanup the Downloads folder in the current profile
forfiles -p "%USERPROFILE%\Downloads" -m * /D -10 /C "cmd /c del /s/q #path > nul 2> nul"
forfiles -p "%USERPROFILE%\Downloads" -m * /D -10 /C "cmd /c rd /s/q #path > nul 2> nul"
#endlocal
#echo on

Running Commands in Batch FIle

I am trying to create a batch file to run start some micro services and database
1 FOR /F "tokens=4 delims= " %%P IN ('netstat -a -n -o ^| findstr :1000') DO #ECHO TaskKill.exe /PID %%P
2 FOR /F "tokens=4 delims= " %%P IN ('netstat -a -n -o ^| findstr :1001') DO #ECHO TaskKill.exe /PID %%P
3 FOR /F "tokens=4 delims= " %%P IN ('netstat -a -n -o ^| findstr :5432') DO #ECHO TaskKill.exe /PID %%P
4 start cd "C:\Program Files\PostgreSQL\10\bin\" & pg_ctl.exe -D "c:\Program Files\PostgreSQL\10\data" start
#REM to start service
5 start javaw -jar -Dserver.port=1000 text-annotation-tool-1.0-SNAPSHOT.jar
Line 1 to 3 and Line 5 execute correctly when executed by commenting line 4.
Line 4 is to start a Postgres server in a new prompt (beacuse of the Dir change). I think the problem is with the way I have used quotes. The 'start' at the beginning and ending of line 4 serve different purpose.
Also, if I execute line 4 in different prompt, How do I close the prompt after execution (nohup equivalent)
There are two errors: You can't "pass" cd to the start command. And start has the quirk to interpret the first quoted parameter as the new window's title. So start "C:\Program Files\PostgreSQL\10\bin\" ... wouldn't work, you need to supply a dummy window title. The & also seems wrong
So you need:
start "Postgres Server" "C:\Program Files\PostgreSQL\10\bin\pg_ctl.exe" -D "c:\Program Files\PostgreSQL\10\data" start
As the full path to pg_ctl.exe is supplied, there is no need for a cd.
But if you want to define the default directory for the new process, you have to use the /D parameter:
start "Postgres Server" /D "C:\Program Files\PostgreSQL\10\bin" pg_ctl.exe -D "c:\Program Files\PostgreSQL\10\data" start
Unrelated, but: putting the Postgres data directory into c:\Program Files\ is a very bad idea. That directory has special permissions for a purpose. You should use %ProgramData% or %AppData% instead

Remote service checking batch file not quite working

Here is my pseudo:
Read from LIST
Ping to check if machine is awake | Report result
Check to see if SERVICE is running | Report result
NO? Is it stopped?
YES? Run it | Report result
NO? Must not be installed, remote install please! | Report result
This is driving me bonkers here... I can make the parts of this code work alone just fine, but when I combine it into a nested IF structure, it returns 'Network Error' and 'Running' if a machine does not have the service running...then a manual check at that machine shows it is still actually stopped. Same for machines without the service installed at all.Please tell me where I'm messing up.. Thanks!
#echo off
echo.
echo.
cls
set SERVICE=MyServ
for /f %%i in (\\127.0.0.1\c$\list.txt) do call :DOIT %%i
:DOIT
echo Checking %SERVICE% on %1
#ECHO off
ping -n 2 -w 1000 %1 >trial.txt
find "Reply from" trial.txt>nul
if %ERRORLEVEL% == 1 (echo %1 Network Unresponsive>> "\\127.0.0.1\c$\list_report.txt")
if %ERRORLEVEL% == 0 (
sc \\%1 query %SERVICE% | FIND "STATE" | FIND "RUNNING"
if %ERRORLEVEL% == 0 (echo %1 Running>> "\\127.0.0.1\c$\list_report.txt")
if not %ERRORLEVEL% == 0 (
sc \\%1 query %SERVICE% | FIND "STATE" | FIND "STOPPED"
if %ERRORLEVEL% == 0 (
sc \\%1 start %SERVICE%
echo %1 forced start>> "\\127.0.0.1\c$\list_report.txt""
)
if not %ERRORLEVEL% == 0 (
xcopy /f /y "\\127.0.0.1\!\theAPP.exe" "\\%1\c$\temp\"
\\127.0.0.1\!\psexec \\%1 -s -n 10 -d cmd /c "c:\temp\theAPP.exe"
echo %1 Installed>> "\\127.0.0.1\c$\list_report.txt""
)
)
)
this should fix the issue
for /f %%i in (\\127.0.0.1\c$\list.txt) do call :DOIT %%i
:DOIT
if not "%1"=="" (
echo Checking %SERVICE% on %1
echo.
ping -n 2 -w 1000 %1 | find "Reply from" >nul
if ERRORLEVEL 1 echo %1 Network Unresponsive>> \\127.0.0.1\c$\list_report.txt else (
sc \\%1 query %SERVICE% | find "RUNNING" > nul
if ERRORLEVEL 1 (
sc \\%1 start %SERVICE% > nul
echo %1 Forced Start>> \\127.0.0.1\c$\list_report.txt
) else (
echo %1 Running>> \\127.0.0.1\c$\list_report.txt)
xcopy /f /y \\127.0.0.1\c$\text.txt \\%1\c$\temp\ > nul
\\127.0.0.1\c$\psexec \\%1 -s -n 10 -d cmd /c "type c:\temp\text.txt"
echo %1 Installed>> "\\127.0.0.1\c$\list_report.txt")
)
)
part of the issue is that you have to test for if not %1="" at the top of the script. that is where you get the erroneous text..
then you had some nesting issues, so i used ELSE instead.
you will have to change the text.txt to your filename.exe (and omit the "type" command)
please check answer if this solves your problem
fyi, you will need to have administrator access on the remote machine so that you can turn on and off services

PSEXEC INPUT REDIRECTION

I am using Psexec to run a remote batch file. I pass input to psexec and redirect it to the remote batch file which seeks a filename as its input. However while redirecting, the file name becomes a garbage as ###&#* which means actual file name is not passed to batch file which the user gives. can anyone tell what might be the reason for this.
pause
cd c:
set /P INPUT=Type input: %=%
echo Your input was: %INPUT%
copy %INPUT% \\remotemachineip\C$ && c:\psexec \\machineip cmd /k "c:\batchfile.bat arg1 < %INPUT% & del %INPUT%" -e -c -f -i
pause
pause
cd c:
set /P INPUT=Type input: %=%
echo Your input was: %INPUT%
copy %INPUT% \\remotemachineip\C$ && c:\psexec \\machineip cmd /k c:\batchfile.bat %INPUT% & del %INPUT% -c -f -i
pause
the remote batch file which seeks input from the above batch file commands on the local machine. so %1(below command) is replaced by the %INPUT%(the second argument in the cmd.exe in the above code content) which the user enters and the sqlcmd command will be executed. so the input which the user passes in the above batch file will be successfully redirected to the below batch file(content) and the command(sqlcmd below) in it will be successfully executed.
SQLCMD -Sservername -d(databasename) -iC:LINKEDSERVER.sql -v filename="%1"
for e.g if I give %INPUT% as c:\inputfile.xls it will be redirected to SQLCMD command in place of %1, so it executes it as--
SQLCMD -Sservername -d(databasename) -iC:LINKEDSERVER.sql -v filename="c:\inputfile.xls"