- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I have a requirement to perform a loop until the condition is met. I have a sample SAS code as an example
%macro test;
%let _timer= %sysfunc(20Sep2024 16:00)
data want;
dur=datetime - &_timer;
hour=hour(dur);
run;
%mend
I have to run this code everyday and if the hour output is within 0 to 24 , I have to perform few steps and if is not within 0 to 24, then I have to sleep for 30 mins and execute the macro again to check for hour output.
I have written the code as like below
%test;
data have;
set want;
if ( 0 <= hour <=24 ); then put 'Job completed'
else
call sleep(1800);
%test;
run;
I'm strugglying to write a loop condition for this scenario. Please help me out.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Usually instead of having a SAS program that runs forever (sleeping for 30 minutes at a time), it's better to have a job that runs once, and then schedule that job to run every 30 minutes. Do you have access to job scheduling tools on in your environment? It can be as simple as windows scheduler or cron on linux, or dedicated scheduling tools like LSF/flow manager.
Next up: Troy Martin Hughes presents Calling Open-Source Python Functions within SAS PROC FCMP: A Google Maps API Geocoding Adventure on Wednesday April 23.
Register now at https://www.basug.org/events.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your response. Yes, we do have LSF in our environment, but problem is that there are lot of SAS schedule flows after this particular job, Its very unlikely to run this job once ( as you said ) ,. So thats the reason we planned to write the logic at the program level and based on this output all successor job will get kick started.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@freshstarter wrote:
Thanks for your response. Yes, we do have LSF in our environment, but problem is that there are lot of SAS schedule flows after this particular job, Its very unlikely to run this job once ( as you said ) ,. So thats the reason we planned to write the logic at the program level and based on this output all successor job will get kick started.
Not sure what that means. How would your proposed SAS DO loop work to help fix the issue?
Do you mean that there is a chain of jobs (steps?) scheduled? How does that work? Do the later ones runs only when the first one completes "successfully"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Agreeing with @Quentin
However, I already wrote the code, so here it is:
%let _timer='25SEP2024:13:30:00'dt;
data want;
dur=0;
do while(dur<=24);
dur=(datetime()-&_timer)/3600;
call sleep(1800);
end;
put 'Job Completed';
run;
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
There are two different loop structures that have a behavior similar to what you describe: DO UNTIL and DO WHILE.
Both pretty much require a very clearly stated stopping rule for a given start. I am not sure what "loop" start or end you want.
This does nothing but throw errors:
%let _timer= %sysfunc(20Sep2024 16:00); data want; dur=datetime - &_timer; hour=hour(dur); run;
And the LOG
29 %let _timer= %sysfunc(20Sep2024 16:00); ERROR: Function name missing in %SYSFUNC or %QSYSFUNC macro function reference. 30 31 data want; 32 dur=datetime - &_timer; NOTE: Line generated by the macro variable "_TIMER". 1 Sep2024 16:00) -- 388 200 ------- 68 ERROR 388-185: Expecting an arithmetic operator. ERROR 200-322: The symbol is not recognized and will be ignored. ERROR 68-185: The function SEP2024 is unknown, or cannot be accessed. 33 hour=hour(dur); 34 run;
%sysfunc requires a function. You didn't provide one so that is one error.
So you have to describe a bit better what you think that code is supposed to do.
If you want to provide a specific datetime value then it should appear as either a literal like "20Sep2024 16:00"DT or the result of some function calls.
This: "if the hour output is within 0 to 24 " is pretty much meaningless as all HOUR values in SAS will be in that interval and the HOUR function will only return values of 0 to 23.
So you need to provide 1) a clearer description of what you expect for "hour" 2) the stopping rule for any any Do Until or Do While.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thanks ..Just now I have realised hour function will not output beyond 23. I have changed the logic to use date function for my logic. Below is my code.
This code I will be executing on start day of month and it will check for the trigger file based on last modified time. If the trigger file is within in the last 2 days, then it should complete the job otherwise the job should be waiting until the trigger file is received ( Please note I cant use file exists as the trigger file will not be removed by the owner and it will be ovwewritten always, thats the reason Im using last modified time function) . So I thought of using sleep function for 30mins and again the code should check for trigger file. This should be in loop always until my condition is met.
Below code is not meeting my requirement.
filename fname 'C:\test_loop.txt';
data want ;
fid = fopen('fname');
if fid then do ;
flm = finfo(fid,'Last Modified');
lm=put(datepart(input(flm,anydtdtm60.)),date9.);
lm2=input(lm,date9.);
format lm2 date9.;
end;
else put ' No file';
run;
data have;
set want;
days_diff=intck('day',lm2,today());
do while (days_diff <=2);
call sleep(1800);
end;
put 'Job Completed';
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
If you've got an LSF license that also allows to schedule non-SAS jobs then below should work.
If you can only schedule SAS jobs then as long as you can issue OS commands out of SAS jobs (XCMD) then all that would be required is to formulate part of below logic in SAS syntax (which of course is less efficient because for each call SAS needs to be invoked).
Questions:
1. Is below logic what you're trying to achieve?
2. Do you need this in SAS syntax or can you also schedule bash scripts?
Using Copilot with below prompts:
Got it! To rerun an LSF job at regular intervals until a file’s modified date is within the last 24 hours, you can modify the previous script to include this specific condition check. Here’s how you can do it:
- Job Script: This is the script that performs your task.
- Wrapper Script: This script submits the job and checks the file’s modified date.
Here’s an example of the wrapper script:
#!/bin/bash
# Define the condition check function
check_condition() {
# Replace /path/to/your/file with the actual file path
file="/path/to/your/file"
# Get the current time and the file's modified time
current_time=$(date +%s)
file_mod_time=$(stat -c %Y "$file")
# Calculate the time difference in seconds
time_diff=$((current_time - file_mod_time))
# Check if the file was modified within the last 24 hours (86400 seconds)
if [ $time_diff -le 86400 ]; then
return 0 # Condition met
else
return 1 # Condition not met
fi
}
# Submit the job to LSF
bsub < your_job_script.sh
# Loop until the condition is met
while ! check_condition; do
# Wait for a specified interval before rerunning the job
sleep 600 # Wait for 10 minutes (600 seconds)
# Resubmit the job
bsub < your_job_script.sh
done
In this script:
- The
check_condition
function checks if the file’s modified time is within the last 24 hours. - The
stat -c %Y "$file"
command retrieves the file’s last modified time in seconds since the epoch. - The
time_diff
variable calculates the difference between the current time and the file’s modified time. - The script resubmits the job every 10 minutes until the condition is met.
You can adjust the file path, sleep interval, and other parameters as needed for your specific use case.
Does this look like what you need?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Here the SAS code portion that returns an indicator macro variable if the condition is met or not.
%macro check_mod_date(file_name);
data info;
length infoname infoval $60;
rc=filename('ext_file', "&file_name");
fid=fopen('ext_file');
infonum=foptnum(fid);
do i=1 to infonum;
infoname=foptname(fid, i);
if find(infoname,'Last Modified','it') then
do;
infoval=finfo(fid, infoname);
last_modified_dttm=input(infoval,datetime18.);
if datetime()-last_modified_dttm<86400 then condition_met_flg=1;
else condition_met_flg=0;
leave;
end;
end;
call symputx('condition_met_flg',condition_met_flg,'g');
close=fclose(fid);
rc=filename('ext_file');
run;
%mend;
%check_mod_date(C:\temp\create_data.sas);
%put &=condition_met_flg;
54 %put &=condition_met_flg; CONDITION_MET_FLG=1