Multiple Ifs in Batch - if-statement

I've tried multiple times to get this batch to work but it won't and it's driving me crazy. I've also combed this website and tried many different things before I gave in to asking the question.
I have a batch that will do a shutdown or reboot or logoff depending on what choice you pick. The problem comes in when I run this and want to move from hours to minutes to seconds by checking the answer to see if it's zero. It gives the error "There was an unexpected (" and immediately closes. If I pull this apart and run it individually it works.
Here is the main function that includes the If statement. If you want to look at the entire batch I can give it to you. I've commented out the actual use of shutdown just to help with figuring this out. The 2 lines preceeding the REM'd out shutdown line will be removed when this is figured out.
:SR_MAIN
cls
echo+
echo+
set /p SR_hrs=....Please enter the number of hours before %SR_NAME%:
IF "%SR_hrs%" == 0 (
echo+
echo You don't want hours, huh?
timeout /t 2 > nul
cls
echo+
echo+
set /p ptm=....Please enter the number of minutes before %SR_NAME%:
IF %ptm% == 0 (
echo+
echo You don't want minutes, huh?
timeout /t 2 > nul
cls
echo+
echo+
set /p pts=....Please enter the number of seconds before %SR_NAME%:
IF %pts% == 0 (
echo+
echo Exiting to Shutdown menu...
timeout /t 2 > nul
goto SHUTREMENU
) ELSE (
cls
echo+
echo+
echo This will %SR_NAME% the computer in the seconds you provided.
set /a tm=pts
echo+
echo Waiting %tm% seconds before continuing...
echo+
timeout /t %tm%
echo Now would come the %SR_NAME%!
pause
REM shutdown /f /%SR_N% /t 0
exit
)
) ELSE (
cls
echo+
echo+
echo This will %SR_NAME% the computer in the minutes you provided.
set /a tm=ptm*60
echo+
echo Waiting %ptm% minutes (%tm% seconds) before continuing...
echo+
timeout /t %tm%
echo Now would come the %SR_NAME%!
pause
REM shutdown /f /%SR_N% /t 0
exit
)
) ELSE (
cls
echo+
echo+
echo This will %SR_NAME% the computer in the hours you provided.
set /a tm=SR_hrs*60*60
echo+
echo Waiting %SR_hrs% hours (%tm% seconds) before continuing...
echo+
timeout /t %tm%
echo Now would come the %SR_NAME%!
pause
REM shutdown /f /%SR_N% /t 0
exit
)
:MAIN_MENU
ECHO Exiting to Main Menu...
PAUSE
Thanks for any help you can give. This one has been a real puzzle to me.
J

There's a percent sign missing.
IF "%SR_hrs%" == 0 (
↑ there

Sebastian pointed out the missing %.
Your other problem is the expansion of variables will not work inside the same code block that sets the variable. The entire code block is parsed before anything is executed, and code like %ptm% is expanded at parse time. So you are getting the value of ptm before it was set!
The solution is to use delayed expansion.
Put setlocal enableDelayedExpansion near the top of your script.
Then use !var! instead of %var% within your blocks of code.
For more info about delayed expansion, type help set from the command line, and read from the point it says "Finally, support for delayed environment variable expansion..."

Related

Informatica Looping

I am looking for information on looping in Informatica. Specifically, I need to check if a source table has been loaded, if it has, move to next step, if not wait X minutes and check the status table again. I would prefer direction to a place I can learn this on my own, but I need to confirm this is even possible as I have not found anything on my google searches.
You can use a simple shell script to do this wait and watch capability.
#/bin/sh
# call it as script_name.sh
# it will wait for 10 min and check again for data, in total it will wait for 2hours. change them if you want to
# Source is assumed as oracle. change it as per your source.
interval=600
loop_count=10
counter=0
while true
do
$counter=`expr $counter + 1 `
db_value=`sqlplus -s user/pass#local_SID <<EOF
set heading off
set feedback off
SELECT count(*) FROM my_source_table;
exit
EOF`;
if [ $db_value -gt 0 ]; then
echo "Data Found."
exit 0
else
if [ $counter -eq $loop_count ]
then
echo "No data found in source after 2hours"
exit 1
else
sleep $interval
fi
fi
done
And add this shell script(in a CMD task) to the beginning of the workflow.
Then use informatica link condition as if status= 0, proceed else email that wait time is over.
You can refer to the pic below. This will send a mail if wait time is over and still data is not there in source.
In general, looping is not supported in Informatica PowerCenter.
One way is to use scripts, as discussed by Koushik.
Another way to do that is to have a Continuously Running Workflow with a timer. This is configurable on Scheduler tab of your workflow:
Such configuration makes the workflow start again right after it succeeds. Over and over again.
Workflow would look like:
Start -> s_check_source -> Decision -> timer
|-> s_do_other_stuff -> timer
This way it will check source. Then if it has not been loaded trigger the timer. Thet it will succeed and get triggered again.
If source turns out to be loaded, it will trigger the other session, complete and probably you'd need another timer here to wait till next day. Or basically till whenever you'd like the workflow to be triggered again.

How to kill a C++ program after say t seconds in Windows Command Prompt? [duplicate]

I would like to start a program with a windows batch file. But the program should stop after a certain timeout value. For example: Run the program 60 seconds and stop it after 60 seconds.
Under Linux, there is this nice timeout command to do what I want. Windows has also a timeout command, but its just to pause a command, to delay its execution. Is there something else under Windows to do so ?
Setup: Windows 7, 64 Bit, Professional
start yourprogram.exe
timeout /t 60
taskkill /im yourprogram.exe /f
Bali C gave a concise and to the point answer.
I needed something a little more featureful and reusable.
Based on Bali C's Example. I came up with this.
If anyone should need the same as me.
your.bat
REM...
CALL STARTwaitKILL..bat /relative/path/your_program.exe
REM...
STARTwaitKILL.BAT
#ECHO OFF
IF[%1]==[] GOTO EOF
IF NOT EXIST %1 GOTO EOF
REM SET PRIORITY=/NORMAL
REM ADJUST PRIORITY, BELOWNORMAL LETS BATCH FILE RUN MORE SMOOTHLY
REM WITH A PROGRAM THAT CONSUMES MORE CPU. SEE ABOUT MAXWAIT BELLOW
SET PRIORITY=/BELOWNORMAL
REM SET PRIORITY=/LOW
REM 0 NORMAL WINDOW :: 1 NO WINDOW :: 2 MINIMIZED WINDOW
SET /A HIDDEN=1
REM MAXWAIT HERE IS MORE LIKE MINIMUM WAIT IN WINDOWS.
SET MAXWAIT=10
SET WAITCOUNT=0
SET ARGS=/I %PRIORITY%
IF %HIDDEN% EQU 1 SET ARGS=%ARGS% /B
IF %HIDDEN% EQU 2 SET ARGS=%ARGS% /MIN
START %ARGS% %1
:WAIT
IF %WAITCOUNT% GEQ %MAXWAIT% GOTO KILL_IT
TIMEOUT /T 1 > NUL
SET /A WAITCOUNT+=1
FOR /F "delims=" %%a IN ('TASKLIST ^| FIND /C "%~nx1"') DO IF %%a EQU 0 GOTO RUN_DONE
GOTO WAIT
:KILL_IT
TASKKILL /IM %~nx1 /F > NUL
:RUN_DONE
Could be fleshed out ore to take more arguments for priority and such, but I don't have the need for it. Shouldn't be hard to add.
Don't exist any command in Windows to delay an app or to set a timeout for an app
Timeout in Windows is for Delay the execution process of CMD/Batfile, nothing more utility.
You can use external tools for that, I don't remember the name of any now, so many underground software, sorry, but I remember that in the autoit official forum exists a similar commandline tool to launch an app setting the timeout,
and maybe in the tool NIRCMD, or ps2exec, check their help files, or someone inside the WAIK Kits.
This is the only you can do:
#Echo OFF
:: First launch the app in background mode, because some applications stops the execution of CMD.
Start /B ".\Dir\Your app.exe"
:: Then stay in background for a certain time
Timeout /T "Seconds"
:: Continue your code...
Pause&Exit
The start+timeout+taskkill waits exactly the given time. Since I needed to stop waiting if the process exits earlier, I created my own solution in C++.
The tuxliketimeout program mimics the GNU timeout. Feel free to download&compile from
https://github.com/cernoch/tuxliketimeout
In windows 10 the easiest way is with scriptrunner:
Demonstrate the timeout by running a pause command (this will kill the called process):
ScriptRunner.exe -appvscript cmd "/c" "pause" -appvscriptrunnerparameters -wait -timeout=20

Shell script to terminate program but causes output file to not be written

I am wanting to run a program in the background that collects some performance data and then run an application in the foreground. When the foreground application finishes it detects this and the closes the application in the background. The issue is that when the background application closes without first closing the file, I'm assuming, the output of the file remains empty. Is there a way to constantly write the output file so that if the background application unexpectedly closes the output is preserved?
Here is my shell script:
./background_application -o=output.csv &
background_pid=$!
./foreground_application
ps -a | grep foreground_application
if pgrep foreground_application > /dev/null
then
result=1
else
result=0
fi
while [ result -ne 0 ]
do
if pgrep RPx > /dev/null
then
result=1
else
result=0
fi
sleep 10
done
kill $background_pid
echo "Finished"
I have access to the source code for the background application written in C++ it is a basic loop and runs fflush(outputfile) every loop iteration.
This would be shorter:
./background_application -o=output.csv &
background_pid=$!
./foreground_application
cp output.csv output_last_look.csv
kill $background_pid
echo "Finished"

Detect end of process from a sub-shell in ksh

I launch a master script : master.ksh
I want to do some background task during the work of master.ksh.
For this, I created an script sourced at the beggining of master.ksh : slave.ksh with a $
./slave.ksh &
here is the code of slave.ksh:
#!/bin/ksh
touch tmpfile
export thepid=$!
while [[`if [ -n "$thepid" ];fi`]]; do
pwd >> tmpfile
#other set of commands ...
export thepid=$!
done
thepid is used to monitor the pid of the master.ksh, when master.ksh ends, I expect the end of the slave.ksh too and so, the exit of slave.ksh too
but I get an error from slave.ksh :
syntax error at line 5; fi unexpected
if I delete fi , I get another error. What is the good way to test $thepid ?
...
I'm not sure where to begin. This is broken in at least three ways: shell variables don't work that way, if statements don't work that way, and conditionals don't work that way.
Here's one way to do it (tested on 93u+):
> cat master.ksh
#!/bin/ksh -eu
print master says hi
./slave.ksh&
sleep 5
print master says bye
> cat slave.ksh
#!/bin/ksh -eu
print slave says hi
while (($(ps oppid= $$)==$PPID))
do
# work
print slave working....
sleep 1
done
print slave says bye
> ./master.ksh
master says hi
slave says hi
slave working....
slave working....
slave working....
slave working....
slave working....
master says bye
> slave says bye
This compares the PPID shell variable, which appears to be set at process launch, to the parent process id as returned by the linux ps tool, which returns the true current value. This works because when a process dies, any child processes it had have their parent process changed to 1 (init). So the slave works as long as its original PPID matches its current PPID, and then exits.

Automate gdb: show backtrace every 10 ms

I want to write a script for gdb, which will save backtrace (stack) of process every 10 ms. How can I do this?
It can be smth like call graph profiling for 'penniless' (for people, who can't use any sort of advanced profiler).
Yes, there are a lot of advanced profilers. For popular CPUs and for popular OSes. Shark is very impressive and easy to use, but I want to get a basic functionality with such script, working with gdb.
Can you get lsstack? Perhaps you could run that from a script outside your app. Why 10ms? Percentages will be about the same at 100ms or more. If the app is too fast, you could artificially slow it down with an outer loop, and that wouldn't change the percentages either. For that matter, you could just use Ctrl-C to get the samples manually under gdb, if the app runs long enough and if your goal is to find out where the performance problems are.
(1) Manual. Execute the following in a shell. Keep pressing Ctrl+C repeatedly on shell prompt.
gdb -x print_callstack.gdb -p pid
or, (2) send signals to pid repeatedly same number of times on another shell as in below loop
let count=0; \
while [ $count -le 100 ]; do \
kill -INT pid ; sleep 0.10; \
let $count=$count+1; \
done
The source of print_callstack.gdb from (1) is as below:
set pagination 0
set $count = 0
while $count < 100
backtrace
continue
set $count = $count + 1
end
detach
quit
man page of pstack https://linux.die.net/man/1/pstack
cat > gdb.run
set pagination 0
backtrace
continue
backtrace
continue
... as many more backtrace + continue's as needed
backtrace
continue
detach
quit
Of course, omit the duplicate newlines, how do you do single newlines in this forum software? :(
gdb -x gdb.run -p $pid
Then just use do
kill -INT $pid ; sleep 0.01
in a loop in another script.
kill -INT is what the OS does when you hit ctrl-C. Exercise for the reader: make the gdb script use a loop with $n iterations.