webMethods rotate log now by calling special method - logrotate

Is it possible to rotate a logfile immediately in webMethods - by calling a special method or whatever. I do not want to use third-party software.
Further explanation
I need this rotation for both. The default logfile(s) (e.g. server.log) and custom logfiles.

By default webMethods logs (all components such IS, MWS, Optimize etc) rotate every 24h on midnight. You can change that interval by modifying an extended property.
For IntegrationServer 9.6 and lower it is watt.server.logRotateInterval (in milliseconds).
Please note: The watt.server.logRotateInterval parameter was removed from Integration Server after
8.2 SP2. When it was reintroduced for the following fixes, the scope of the parameter changed so that it affected only the stats.log:
IS_9.0_SP1_Core_Fix6
IS_9.5_SP1_Core_Fix3
IS_9.6_Core_Fix2
Starting with Integration Server 9.7, this server configuration parameter has been renamed watt.server.statsLogRotateInterval (in minutes instead of milliseconds), but affects only stats.log file as well.
So I think there is no way to change the log rotate interval. For compressing the old log files I think the best solution would be to write a service that does that and used that service to create a scheduled task (executed daily after midnight).

Related

In Anylogic, is it possible to send an agent from one storage to another directly?

I have 2 storages (called storageA & storageB) and I want to move an agent (pallet) from one to the other via forklifts. I have set up the following.
A pallet is created at a node and is moved to storageA via 'store'. This part works fine. The pallet is then moved to storageB via 'store1' after a delay. This is when the following error occurs:
Exception during discrete event execution:
root.store1.seizeTrans.freeSpaceSendTo:
Path not found! {agent=2, source={level=level, pos=(1673.3333333333333, 3245.0, 0.0)}, target={level=level, pos=(1857.25, 3160.4845, 0.0)}}
It works if I replace 'store1' with a retrieve block and send it to a node first. However I would like to send the pallet directly to another storage rather than via another location. Is this possible?
Please let me know if I have not provided enough information.
Thanks
yeah unfortunately you can't do that as far as I know, the solution I use is the following, which is actually not a super robust solution... but has been ok in applications so far
Place a retrieve block between your delay and your store1
Use the agent you pick up as destination:
on the on seize action of the retrieve block do:agent.transporter=unit;
4.On the store1 block put the highest priority for the task
5. ON the store1 block use resource custom transporter choice: agent.transporter.equals(unit)
6. The dispatching policy should be nearest to the agent in store1, but doing all the above ensures that the resource continues doing the task no matter what... by only using the dispatch policy your model will work 99.999999% of the time... the problem occurs only if another task with higher priority occurs at the exact same time as the transporter is released in the retrieve block, which is rare, but can happen.
I had the same question today so I landed here. But luckily, only after the second step written above, the whole process needed did already work for my case. We can move an agent from one storage to another by simply set the destination of the 'retrieve' block to the coordinate of the agent and the move to independently instead of by fleets or resources. after that we put the 'store' block.
Destination is: (x,y,z)
X: agent.getX()
Y: agent.getY()
Z: agent.getZ()
after agents being retrieved to a specified coordinate, it seems that fleets do not comply paths in the network anymore

Matlab Compiler: protecting re-distribution of software during installation

I'm considering using Matlab Compiler to distribute software for a price. I'm investigating (very) simple methods to discourage re-distribution without annoying users. Any recommendations?
One thought is to email a user a license key and have them input this during the installation process to be verified on a license server. If the key matches what is on the server, the installation proceeds as usual, otherwise, a warning message is shown to inform the user to purchase another license. However, this method requires a specified function to run only during the installation process, and not thereafter (so as not to annoy the user). Is this possible using Matlab Compiler or otherwise?
I suppose I could create a file on the user's disk that the program looks for when it starts (if it exists, then it is not being run for the first time), but if the user copies the whole directory, that file would get copied too.
In order to create an effective licensing system, you have to link it to one or more properties of a user machine (MAC address, OS ID, hard disk serial numbers, CPU serial numbers, etc...).
If you don't to this, you are just going to release licenses that can be transferred from one user to another. If one user decides to spread his license file worldwide, you are doomed because everyone could potentially take that license file and use it to unlock your application.
But if you link your license files to one or more properties of a user machine, as mentioned above, you must be able to obtain these properties either:
before the user decides to buy your application;
when the user activates his license.
First Scenario
You release your software as a trial. When it is started for the first time, you set an expiration date in the registry or in a file well hidden somewhere. You check against the expiration date when the application starts and, once it is reached, you throw an error and you don't let the used play with your application anymore.
Within the application, you create a Register Now button somewhere. When it is clicked, the application retrieves the machine properties and passes them to the web page / form that will be opened to let the user perform the payment. That page will be in charge to validate the machine properties, receive the payment and, finally, deliver a valid license code based on these properties.
Within the application, you must implement the same logics that allowed your form to create the license code, because you will need to use them in order to validate the code itself every time your application starts. A pseudo-code example:
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lc = GetLicenseCode();
if (~strcmp(sha1([mp1 mp2 mp3]),lc))
errordlg('Invalid license code!');
return;
end
This is the simplest path. But keep in mind that if one or more properties of the user machine change (because he changes a device or reinstalls his OS), his license will be invalidated and you will have to provide a customer assistance service that takes care of this kind of situations.
Second Scenario
This one is much harder. You will not be able to know the user's machine properties in advance. So your licensing system will work on a two-steps basis. You release a unique code (called LID for example) when the used purchases your application. Then, once the user inserts that it in your application, your application must send it back together with the machine properties. The final key (called LKey for example) is then computed and sent back to the user.
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lkey = GetLicenseKey();
if (~strcmp(sha1([mp1 mp2 mp3]),lkey))
errordlg('Invalid license code!');
return;
end
Machine Properties
The first solution has been provided to you through a comment: the MachineGuid value located in the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography. It's pretty solid. But it will only work on Windows machines. Use winqueryreg to access the registry.
Another good alternative is the Window Domain Controller Security ID, which is another machine-specific unique identifier. You can retrieve it using Java code within Matlab:
wdc_sid = com.sun.security.auth.module.NTSystem.getDomainSID();
or through the Windows registry key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\GroupMembership. The registry approach should be the one to use if you want to maintain a certain backward compatibility with old Matlab releases. Unfortunately, the Window Domain Controller Security ID is another identifier that is available only on machines that run under Windows.
If you want to adapt your licensing system to every possible OS and environment, you have to use a more generic approach, based on universally accessible hardware properties: MAC adresses, hard disk serials and such things. As far as I know, the most reliable property is the MAC address, because its uniqueness, althrough not granted, is almost certain and it's very unfrequent to change a network adapter (there are more chances to break an hard disk actually). Retrieve the MAC adresses of the machine network adapters using Java code as follows:
mac_addrs = '';
net_int = java.net.NetworkInterface.getNetworkInterfaces();
while (net_int.hasMoreElements)
mac_addr = net_int.nextElement.getHardwareAddress();
if (~isempty(mac_addr))
mac_addrs = [mac_addrs, '-', sprintf('%.2X',typecast(mac_addr,'uint8'))];
end
end
mac_addrs = mac_addrs(2:end);
The above computation produces a character array that represents the result of the concatenation of all the MAC addresses found on the machine. Again, for compatibility reasons, this may not work on old Matlab releases, so you have to use a much more complex approach, described here.
[EDIT]
This approach to retrieve the MAC address based on the underlying OS could be easier:
switch computer('arch')
case {'maci','maci64'}
[~,a]=system('ifconfig');
c=strfind(a,'en0');if ~isempty(c),a=a(c:end);end
c=strfind(a,'en1');if ~isempty(c),a=a(1:c-1);end
% find the mac address
b=strfind(a,'ether');
mac_add=a(1,b(1)+6:b(1)+22);
case {'win32','win64'}
[~,a]=system('getmac');b=strfind(a,'=');
mac_add=a(b(end)+1:b(end)+19);
case {'glnx86','glnxa64'}
[~,a]=system('ifconfig');b=strfind(a,'Ether');
mac_add=a(1,b(1)+17:b(1)+33);
otherwise,mac_add=[];
end
I found it in the comments of this article.

How does Solaris SMF determine if something is to be in maintenance or to be restarted?

I have a daemon process that I wrote being executed by SMF. The problem is when an error occurs, I have fail code and then it will need to restart from scratch. Right now it is sending sys.exit(0) (Python), but SMF keeps throwing it in maintenance mode.
I've worked with SMF enough to know that it sometimes auto-restarts certain services (and lets others fail and have you deal with them like this). How do I classify this process as one that needs to auto-restart? Is it an SMF setting, a method of failing, what?
Manpage
Solaris uses a combination of startd/critical_failure_count and startd/critical_failure_period as described in the svc.startd manpage:
startd/critical_failure_count
startd/critical_failure_period
The critical_failure_count and critical_failure_period properties together specify the maximum number of service failures allowed in a given time interval before svc.startd transitions the service to maintenance. If the number of failures exceeds critical_failure_count in any period of critical_failure_period seconds, svc.startd will transition the service to maintenance.
Defaults in the source code
The defaults can be found in the source, the value depends on whether the service is "wait style":
if (instance_is_wait_style(inst))
critical_failure_period = RINST_WT_SVC_FAILURE_RATE_NS;
else
critical_failure_period = RINST_FAILURE_RATE_NS;
The defaults are either 5 failures/10 minutes or 5 failures/second:
#define RINST_START_TIMES 5 /* failures to consider */
#define RINST_FAILURE_RATE_NS 600000000000LL /* 1 failure/10 minutes */
#define RINST_WT_SVC_FAILURE_RATE_NS NANOSEC /* 1 failure/second */
These variables can be set in the SMF as properties:
<service_bundle type="manifest" name="npm2es">
<service name="site/npm2es" type="service" version="1">
...
<property_group name="startd" type="framework">
<propval name='critical_failure_count' type='integer' value='10'/>
<propval name='critical_failure_period' type='integer' value='30'/>
<propval name="ignore_error" type="astring" value="core,signal" />
</property_group>
...
</service>
</service_bundle>
TL;DR
After checking against the startd values, If the service is "wait style", it will be throttled to a max restart of 1/sec, until it no longer exits with a non-cfg error. If the service is not "wait style" it will be put into maintenance mode.
Presuming a normal service manifest, I would suspect that you're dropping into maintenance because SMF is restarting you "too quickly" (which is a bit arbitrarily defined). svcs -xv should tell you if that is the case. If it is, SMF is restarting you, and then you're exiting again rapidly and it's decided to give up until the problem is fixed (and you've manually svcadm clear'd it.
I'd wondered if exiting 0 (and indicating success) may cause further confusion, but it doesn't appear that it will.
I don't think Oracle Solaris allows you to tune what SMF considers "too quickly".
You have to create a service manifest. This is more complicated than not. This has example manifests and documents the manifest structure.
http://www.oracle.com/technetwork/server-storage/solaris/solaris-smf-manifest-wp-167902.pdf
As it turns out, I had two pkills in a row to make sure everything was terminated correctly. The second one, naturally, was exiting something other than 0. Changing this to include an exit 0 at the end of the script solved the problem.

Invoke process activity not logging any error in log file

I am trying to use Invoke process to invoke an executable from my windows workflow in my TFS 2010 build.
But when I am looking at the log file it is not logging any error.
I did use WriteBuildMessage and WriteBuildwarning inside my invoke process activity.
I also set the filename,workingdirectory etc in activity.
Can someone please point out why it is not logging?
You can do something like this:
In this case you have to ensure that Message are set as follows:
With those parameters set as depicted, I catch what you seem to be after.
Furthermore, you can check in the Properties of your InvokeProcess: Set the Result into a string-variable and then set in a subsequent WriteBuildMessage this string-variable to be the Message. This way, you 'll additionally catch the return of your invoked process.
EDIT
Another common thing that you 've possibly overlooked is the BuildMessageImportance: if it is not set as High, messages do NOT appear under default Logging Verbosity (= Normal). See here for some background.
In your Invoke Process, you want to set the Result property to update a variable (returns an Int, so lets call it ExitCode), under your Invoke Process (but still in the Agent Scope) you can drop in an If, so you can set the condition of this to ExitCode <> 0 and do whatever you like on a failure (such as failing the build).
Also, as a note, if your WriteBuildMessage is not showing anything in your log, you need to set the Importance to Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High, anything lower and it wont show in the Normal logging level.

Perl CGI gets parameters from a different request to the current URL

This is a weird one. :)
I have a script running under Apache 1.3, with Apache::PerlRun option of mod_perl. It uses the standard CGI.pm module. It's a regularly accessed script on a busy server, accessed over https.
The URL is typically something like...
/script.pl?action=edit&id=47049
Which is then brought into Perl the usual way...
my $action = $cgi->param("action");
my $id = $cgi->param("id");
This has been working successfully for a couple of years. However we started getting support requests this week from our customers who were accessing this script and getting blank pages. We already had a line like the following that put the current URL into a form we use for customers to report an issue about a page...
$cgi->url(-query => 1);
And when we view source of the page, the result of that command is the same URL, but with an entirely different query string.
/script.pl?action=login&user=foo&password=bar
A query string that we recognise as being from a totally different script elsewhere on our system.
However crazy it sounds, it seems that when users are accessing a URL with a query string, the query string that the script is seeing is one from a previous request on another script. Of course the script can't handle that action and outputs nothing.
We have some automated test scripts running to see how often this happens, and it's not every time. To throw some extra confusion into the mix, after an Apache restart, the problem seems to initially disappear completely only to come back later. So whatever is causing it is somehow relieved by a restart, but we can't see how Apache can possibly take the request from one user and mix it up with another.
This, it appears, is an interesting combination of Apache 1.3, mod_perl 1.31, CGI.pm and Apache::GTopLimit.
A bug was logged against CGI.pm in May last year: RT #57184
Which also references CGI.pm params not being cleared?
CGI.pm registers a cleanup handler in order to cleanup all of it's cache.... (line 360)
$r->register_cleanup(\&CGI::_reset_globals);
Apache::GTopLimit (like Apache::SizeLimit mentioned in the bug report) also has a handler like this:
$r->post_connection(\&exit_if_too_big) if $r->is_main;
In pre mod_perl 1.31, post_connection and register_cleanup appears to push onto the stack, while in 1.31 it appears as if the GTopLimit one clobbers the CGI.pm entry. So if your GTopLimit function fires because the Apache process has got to large, then CGI.pm won't be cleaned up, leaving it open to returning the same parameters the next time you use it.
The solution seems to be to change line 360 of CGI.pm to;
$r->push_handlers( 'PerlCleanupHandler', \&CGI::_reset_globals);
Which explicitly pushes the handler onto the list.
Our restart of Apache temporarily resolved the problem because it reduced the size of all the processes and gave GTopLimit no reason to fire.
And we assume it has appeared over the past few weeks because we have increased the size of the Apache process either through new developments which included something that wasn't before.
All tests so far point to this being the issue, so fingers crossed it is!