 |
SoftTree Technologies
Technical Support Forums
|
|
Author |
Message |
Brent
Joined: 20 Feb 2002 Posts: 57
|
|
Calling a JAL script from Ruby |
|
Is it possible to call an external JAL script from a Ruby program, passing in a parameter and receiving back a return value?
If it is possible, what would the Ruby program need to do to call the script and receive the return value?
Thank you.
|
|
Thu Dec 09, 2004 10:12 am |
|
 |
SysOp
Site Admin
Joined: 26 Nov 2006 Posts: 7970
|
|
Re: Calling a JAL script from Ruby |
|
Sorry I've never heard of Ruby before and cannot say what you can do with it and what you cannot. You can surely execute an external JAL script from batch jobs and other programs. There exist several methods for doing that but the most simple is to use a permanent JAL script job whose only script line is like below @SCRIPT: C:\\Scripts\myscript.jal This job will then run a dynamic script referenced in the @SCRIPT tag. To run this job from a batch file or other program run "24x7.EXE /JOB [this job number]" Before you run it you can modify the referenced JAL file any way you want. To return a value back, in the script use any available file, INI, registry, database, etc… methods to temporarily put the return value someplace from where you can then read it from your Ruby program after the JAL script terminates. If you need a simple numeric value as a return code you can call Windows API Proces#####it function (see Ca;; method description in the on-line docs) to kill the job process and return an exit code value to the parent process. Similar things can be done using VBScript jobs in 24x7. : Is it possible to call an external JAL script from a Ruby program, passing in : a parameter and receiving back a return value? : If it is possible, what would the Ruby program need to do to call the script : and receive the return value? : Thank you.
|
|
Thu Dec 09, 2004 11:15 am |
|
 |
Brent
Joined: 20 Feb 2002 Posts: 57
|
|
Re: Calling a JAL script from Ruby |
|
Here is my problem. We have a directory where files are being generated. When they are done being generated, they need to be processed. While the files are being generated, they are locked. Ruby can watch the directory and process the files better than JAL, but JAL is the only language I have seen that can detect when these files are locked. Where would I find these methods you talk about to execute an external JAL script from another program? : Sorry I've never heard of Ruby before and cannot say what you can do with it : and what you cannot. : You can surely execute an external JAL script from batch jobs and other : programs. There exist several methods for doing that but the most simple : is to use a permanent JAL script job whose only script line is like below : @SCRIPT: C:\\Scripts\myscript.jal : This job will then run a dynamic script referenced in the @SCRIPT tag. To run : this job from a batch file or other program run "24x7.EXE /JOB [this : job number]" : Before you run it you can modify the referenced JAL file any way you want. : To return a value back, in the script use any available file, INI, registry, : database, etc… methods to temporarily put the return value someplace from : where you can then read it from your Ruby program after the JAL script : terminates. If you need a simple numeric value as a return code you can : call Windows API Proces#####it function (see Ca;; method description in : the on-line docs) to kill the job process and return an exit code value to : the parent process. : Similar things can be done using VBScript jobs in 24x7.
|
|
Thu Dec 09, 2004 11:51 am |
|
 |
SysOp
Site Admin
Joined: 26 Nov 2006 Posts: 7970
|
|
Re: Calling a JAL script from Ruby |
|
I see now what you want. You really want to execute individual JAL commands or little scripts from some other environment. You can do that only if that environment supports COM automation. You can do that, for example, from VBScript. In such case you can create instantiate 24x7 COM Remote Control object and use 24x7 API to run specific JAL commands as dynamic scripts. For more info see http://www.softtreetech.com/24x7/24x7_COM.pdf. By the way, in 24x7 Scheduler you have several methods for monitoring directories: 1. File-watch schedule job can watch for multiple files using file mask and can also monitor their sizes until the processing is done. The job gets triggered only when all files are done. This is very simple and efficient. 2. JAL script type job using DirWaitForUpdate command setting a system hook for the monitored directory. Run this job on the schedule startup and set it to run asynchronous in the background running "forever". An example is available in the on-line help. 3. JAL script job running periodically and getting list of files, their sizes and dates and comparing all this to results of the previous run. If no changes found it assumes that files are done. This is not very complicated but will require several dozens lines of code. In JAL you can also use FileOpen/FileClose commands with some error handling to check if files are locked. 4. In addition to all that you can check directory monitoring methods available in 24x7 Event Server http://www.softtreetech.com/24x7/24x7es_manual.pdf. Tell me more what you can do in Ruby and cannot do in 24x7 and I will tell you how to do it in 24x7. : Here is my problem. We have a directory where files are being generated. When : they are done being generated, they need to be processed. While the files : are being generated, they are locked. : Ruby can watch the directory and process the files better than JAL, but JAL : is the only language I have seen that can detect when these files are : locked. Where would I find these methods you talk about to execute an : external JAL script from another program?
|
|
Thu Dec 09, 2004 12:22 pm |
|
 |
Brent
Joined: 20 Feb 2002 Posts: 57
|
|
Re: Calling a JAL script from Ruby |
|
Here is what the program is doing: 1. The program runs forever. 2. The program checks a directory for a stop.txt file to cause the program to end (deleting the file before the program ends). 3. The program then calls a method over and over, given the directory to watch. 4. The method searches the given directory for a header file (always ends with _HDR.TXT). When found, the method searches for a matching detail file (always ends with _RPT.TXT). Example: Something_HDR.TXT will match up with Something_RPT.TXT. If the matching files are found, and the they are not locked, the program will merge the two files together and copy them to some destination, or copy them separately for backup purposes. If the merged file exists in the destination, the file is given a number in the name and copied (incrementing the number until a match is not found). The method also searches the directory for other files that end in a certain way for straight copying to some destination. 5. Upon a successful copy, the files in the given directory to the method are deleted. Except for detecting the locked files, I have coded the program to watch one directory in only 122 lines of understandable code (blank lines and comments included in the count). This code includes a method to get the current directory, a method to change the current directory, a method to merge two files and send to the destination folder, a method to copy the other files that need to be copied, a method to process a given directory, and the main processing loop. My dislike of JAL includes its complexity to do tasks. Some examples of tasks (coded in Ruby) are: Dir["STOP.TXT"].each do |file| In Ruby, this will perform a block of code if stop.txt exists in the directory. if file1.gsub("_HDR.TXT","") == file2.gsub("_RPT.TXT","") In Ruby, this one line will allow me to do processing if the first part of file1 matches the first part of file2. while FileTest::exist?(destDir + File::Separator + currentPrint + destExt) uniqueNumber += 1 destExt = "_#{uniqueNumber}_PRT.TXT" end In Ruby, these four lines will allow me to check the destination directory for the merged file, and increment the unique number in the file name until no match is found. I have coded in JAL before, and I know that these tasks are far more complicated in JAL. Thank you for your help. I will check out the PDFs you recommended. : I see now what you want. You really want to execute individual JAL commands : or little scripts from some other environment. You can do that only if : that environment supports COM automation. You can do that, for example, : from VBScript. In such case you can create instantiate 24x7 COM Remote : Control object and use 24x7 API to run specific JAL commands as dynamic : scripts. For more info see http://www.softtreetech.com/24x7/24x7_COM.pdf : . : By the way, in 24x7 Scheduler you have several methods for monitoring : directories: 1. File-watch schedule job can watch for multiple files using : file mask and can also monitor their sizes until the processing is done. : The job gets triggered only when all files are done. This is very simple : and efficient. : 2. JAL script type job using DirWaitForUpdate command setting a system hook : for the monitored directory. Run this job on the schedule startup and set : it to run asynchronous in the background running "forever". An : example is available in the on-line help. : 3. JAL script job running periodically and getting list of files, their sizes : and dates and comparing all this to results of the previous run. If no : changes found it assumes that files are done. This is not very complicated : but will require several dozens lines of code. : In JAL you can also use FileOpen/FileClose commands with some error handling : to check if files are locked. : 4. In addition to all that you can check directory monitoring methods : available in 24x7 Event Server : http://www.softtreetech.com/24x7/24x7es_manual.pdf . : Tell me more what you can do in Ruby and cannot do in 24x7 and I will tell : you how to do it in 24x7.
|
|
Thu Dec 09, 2004 2:53 pm |
|
 |
SysOp
Site Admin
Joined: 26 Nov 2006 Posts: 7970
|
|
Re: Calling a JAL script from Ruby |
|
That sounds pretty simple. JAL is not a pretty language but it does the job. Here is how I would do it. 1 First of all create a new user defined method in the Script Library to check for file locked state. Let's call it IsFileLocked. This method would take one argument of string type for the file name and it will return boolean True/False indicating whether the file is locked or not. Example script: ///////////////////////////////////////// OnErrorGoTo FILE_LOCKED Dim( temp, number ) // Try to open file for reading (file_name is argument name) FileOpen( file_name, "LineMode", "Read", "", file_number ) // If we are here we were able to open the file. Close it and return TRUE FileClose( file_number ) Return( True ) FILE_LOCKED: Return( False) //////////////////////////////////////// 2. Second I would create another method to check if the detail file is present and if yeas return file name, otherwise return an empty string. Let's call this method GetDetail, it will to have an argument for the header file name and it will return a string. This can be done as simple as the following: ///////////////////////////////////////// Dim( len, number ) Dim(detail_name, string ) // header_name is an argument name. Let's calculate file name without _HDR.TXT suffix Length( header_name, len ) Subtract( len, 8, len) // Build detail file name Left( header_name, len, header_name ) Concat( header_name, "_RPT.TXT", detail_name ) // Now, let's check if this file exists Dim( file_found, boolean ) FileExists( detail_file, file_found ) If Then( file_find, GOT_IT) Return( "" ) GOT_IT: Return( detail_name ) //////////////////////////////////////// 3. Third I would create another method to calculate the merge file name. Let's call this method GetReportName, it will have 2 arguments: detail file name and a target directory and it will return a string with the new file name. This could be done as simple as the following: ///////////////////////////////////////// Dim( len, number ) Dim( suffix, number ) Dim( available, string ) Dim( new_name, string ) Dim( temp, string ) // replace source dir with target dir in the file name SplitFileName( detail_name, temp, detail_name ) Concat( target_dir, detail_name, detail_name ) // Check if the name is available without suffix Set( new_name, detail_name) NotFileExists( new_name, available ) IfThen( available, DONE ) // Let's find an unique file number _RPT.TXT suffix ( If uniqueness is the only need and file name is not important, why not simply insert a timestamp suffix?) Length( detail_name, len ) Subtract( len, 8, len) Left( detail_name, len, detail_name ) // Now, let's roll LoopWhile True, END_LOOP Add( suffix, 1, suffix ) ConcatEx( detail_name, suffix, "_RPT.TXT", new_name ) NotFileExists( new_name, available ) IfThen( available, DONE ) END_LOOP: DONE: Return( new_name ) //////////////////////////////////////// 3. Now here is the remaining part. Create job of script type, which will have a schedule [when certain files not found] and specify stop.txt file as the file to watch. In the job script code the following (all together it is less then 122 lines, including locking part and comemnts ): //////////////////////////////////////////////////////////////////////////////////////// Dim( header_list, string ) Dim( header_file, string ) Dim( detail_file, string ) Dim( command, string ) Dim( is_empty, boolean ) Dim( file_lock, boolean) Dim( pid, number ) // Get the list of all header files DirEx( "c:\\whatever\\*_HDR.TXT", header_list ) // Loop through the list and check if detail is available and files are locked or not IsEqual( header_list, "", is_empty ) LoopUntil( is_empty, END_LOOP ) // Get next header file GetToken( ",", header_list, header_file ) // Check for detail (see step 2 above) GetDetail( header_file, detail_file ) IsEqual( detail_file, "", is_empty ) IfThen( is_empty, TRY_NEXT_HEADER) // Check for locks IsFileLocked( header_file, file_lock) IfThen( file_lock, TRY_NEXT_HEADER) IsFileLocked( detail_file, file_lock) IfThen( file_lock, TRY_NEXT_HEADER) // Concat, copy and delete files GetReportName( detail_file, "c:\\whatever is target\\", target_file ) ContactEx( "cmd /C copy \"", header_file, "\" + \"", detail_file, "\" \"", target_file, "\"", command) RunAndWait( command, "", 0, pid ) FileDelete( header_file ) FileDelete( detail_file ) TRY_NEXT_HEADER // check if there are more files in the list IsEqual( header_list, "", is_empty ) END_LOOP: //////////////////////////////////////////////////////////////////////////////////////// : Here is what the program is doing: 1. The program runs forever. : 2. The program checks a directory for a stop.txt file to cause the program to : end (deleting the file before the program ends). : 3. The program then calls a method over and over, given the directory to : watch. : 4. The method searches the given directory for a header file (always ends : with _HDR.TXT). When found, the method searches for a matching detail file : (always ends with _RPT.TXT). Example: Something_HDR.TXT will match up with : Something_RPT.TXT. If the matching files are found, and the they are not : locked, the program will merge the two files together and copy them to : some destination, or copy them separately for backup purposes. If the : merged file exists in the destination, the file is given a number in the : name and copied (incrementing the number until a match is not found). The : method also searches the directory for other files that end in a certain : way for straight copying to some destination. : 5. Upon a successful copy, the files in the given directory to the method are : deleted. : Except for detecting the locked files, I have coded the program to watch one : directory in only 122 lines of understandable code (blank lines and : comments included in the count). This code includes a method to get the : current directory, a method to change the current directory, a method to : merge two files and send to the destination folder, a method to copy the : other files that need to be copied, a method to process a given directory, : and the main processing loop. : My dislike of JAL includes its complexity to do tasks. Some examples of tasks : (coded in Ruby) are: Dir["STOP.TXT"].each do |file| : In Ruby, this will perform a block of code if stop.txt exists in the : directory. : if file1.gsub("_HDR.TXT","") == : file2.gsub("_RPT.TXT","") : In Ruby, this one line will allow me to do processing if the first part of : file1 matches the first part of file2. : while FileTest::exist?(destDir + File::Separator + currentPrint + destExt) : uniqueNumber += 1 : destExt = "_#{uniqueNumber}_PRT.TXT" : end : In Ruby, these four lines will allow me to check the destination directory : for the merged file, and increment the unique number in the file name : until no match is found. : I have coded in JAL before, and I know that these tasks are far more : complicated in JAL. : Thank you for yo ur help. I will check out the PDFs you recommended.
|
|
Thu Dec 09, 2004 5:45 pm |
|
 |
Brent
Joined: 20 Feb 2002 Posts: 57
|
|
Re: Calling a JAL script from Ruby |
|
I just thought you would like to know that after getting back into this, I decided to re-write the process in VBScript. I accomplished the lock detection with this function: Function LockDetected(CompleteFileName) Dim FileForLockTesting, ReturnValue On Error Resume Next Set FileForLockTesting = objFSO.OpenTextFile(CompleteFileName, 8, True) If Err.Number 0 Then ReturnValue = True Else FileForLockTesting.Close Set FileForLockTesting = Nothing ReturnValue = False End If On Error GoTo 0 LockDetected = ReturnValue End Function The rest was almost the same as the Ruby programming. One question, could a save button be placed into the 24x7 editor? : That sounds pretty simple. JAL is not a pretty language but it does the job. : Here is how I would do it. : 1 First of all create a new user defined method in the Script Library to : check for file locked state. Let's call it IsFileLocked. This method would : take one argument of string type for the file name and it will return : boolean True/False indicating whether the file is locked or not. Example : script: ///////////////////////////////////////// : OnErrorGoTo FILE_LOCKED : Dim( temp, number ) : // Try to open file for reading (file_name is argument name) : FileOpen( file_name, "LineMode", "Read", "", : file_number ) : // If we are here we were able to open the file. Close it and return TRUE : FileClose( file_number ) : Return( True ) : FILE_LOCKED: Return( False) : //////////////////////////////////////// : 2. Second I would create another method to check if the detail file is : present and if yeas return file name, otherwise return an empty string. : Let's call this method GetDetail, it will to have an argument for the : header file name and it will return a string. This can be done as simple : as the following: ///////////////////////////////////////// : Dim( len, number ) : Dim(detail_name, string ) : // header_name is an argument name. Let's calculate file name without : _HDR.TXT suffix : Length( header_name, len ) : Subtract( len, 8, len) : // Build detail file name : Left( header_name, len, header_name ) : Concat( header_name, "_RPT.TXT", detail_name ) : // Now, let's check if this file exists : Dim( file_found, boolean ) : FileExists( detail_file, file_found ) : If Then( file_find, GOT_IT) : Return( "" ) : GOT_IT: Return( detail_name ) : //////////////////////////////////////// : 3. Third I would create another method to calculate the merge file name. : Let's call this method GetReportName, it will have 2 arguments: detail : file name and a target directory and it will return a string with the new : file name. This could be done as simple as the following: : ///////////////////////////////////////// : Dim( len, number ) : Dim( suffix, number ) : Dim( available, string ) : Dim( new_name, string ) : Dim( temp, string ) : // replace source dir with target dir in the file name : SplitFileName( detail_name, temp, detail_name ) : Concat( target_dir, detail_name, detail_name ) : // Check if the name is available without suffix : Set( new_name, detail_name) : NotFileExists( new_name, available ) : IfThen( available, DONE ) : // Let's find an unique file number _RPT.TXT suffix ( If uniqueness is the : only need and file name is not important, why not simply insert a : timestamp suffix?) : Length( detail_name, len ) : Subtract( len, 8, len) : Left( detail_name, len, detail_name ) : // Now, let's roll : LoopWhile True, END_LOOP : Add( suffix, 1, suffix ) : ConcatEx( detail_name, suffix, "_RPT.TXT", new_name ) : NotFileExists( new_name, available ) : IfThen( available, DONE ) : END_LOOP: DONE: Return( new_name ) : //////////////////////////////////////// : 3. Now here is the remaining part. Create job of script type, which will have : a schedule [when certain files not found] and specify stop.txt file as the : file to watch. In the job script code the following (all together it is : less then 122 lines, including locking part and comemnts ): : //////////////////////////////////////////////////////////////////////////////////////// : Dim( header_list, string ) : Dim( header_file, string ) : Dim( detail_file, string ) : Dim( command, string ) : Dim( is_empty, boolean ) : Dim( file_lock, boolean) : Dim( pid, number ) : // Get the list of all header files : DirEx( "c:\\whatever\\*_HDR.TXT", header_list ) : // Loop through the list and check if detail is available and files are : locked or not : IsEqual( header_list, "", is_empty ) : LoopUntil( is_empty, END_LOOP ) : // Get next header file : GetToken( ",", header_list, header_file ) : // Check for detail (see step 2 above) : GetDetail( header_file, detail_file ) : IsEqual( detail_file, "", is_empty ) : IfThen( is_empty, TRY_NEXT_HEADER) : // Check for locks : IsFileLocked( header_file, file_lock) : IfThen( file_lock, TRY_NEXT_HEADER) : IsFileLocked( detail_file, file_lock) : IfThen( file_lock, TRY_NEXT_HEADER) : // Concat, copy and delete files : GetReportName( detail_file, "c:\\whatever is target\\", target_file : ) : ContactEx( "cmd /C copy \"", header_file, "\" + : \"", detail_file, "\" \"", target_file, : "\"", command) : RunAndWait( command, "", 0, pid ) : FileDelete( header_file ) : FileDelete( detail_file ) : TRY_NEXT_HEADER : // check if there are more files in the list : IsEqual( header_list, "", is_empty ) : END_LOOP: : ////////////////////////////////////////////////////////////////////////////////////////
|
|
Thu Dec 30, 2004 12:30 pm |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|