I'm attempting to write a launchd agent that runs a simple application for every user that logs in to the Mac OS X system.
I have created a file named com.mycompany.myapp.plist and placed it in /Library/LaunchAgents. The contents of that file are:
{
LimitLoadToSessionType = "Aqua";
StartInterval = 10;
OnDemand = NO;
KeepAlive = YES;
RunAtLoad = YES;
Label = "com.mycompany.myapp";
Program = "/Users/thomi/myapp";
ProgramArguments = (
"/Users/thomi/myapp",
"-l",
"-d",
);
}
Initially I didn't have the StartInterval key set, since I thought the agent would start automatically. The problem is that the agent does not start unless I manually issue the following two commands:
launchctl load -S Aqua -D all
launchctl start com.mycompany.myapp
Firther, when I run launchctl list com.mycompany.myapp I get the following output:
{
"Label" = "com.mycompany.myapp";
"LimitLoadToSessionType" = "System";
"OnDemand" = true;
"LastExitStatus" = 0;
"TimeOut" = 30;
"Program" = "/Users/thomi/myapp";
ProgramArguments = (
"/Users/thomi/myapp",
"-l",
"-d",
);
};
Notice that the LimitLoadToSessionType parameter has changed.
Am I missing something here? Is there a different mechanism to start agents like this? Why has the LimitLoadToSessionType property changed?
Not sure if it's the problem, but I think you shouldn't be specifying both OnDemand/RunAtLoad and KeepAlive together. As I understand the documentation, the KeepAlive key replaces the OnDemand/RunAtLoad combo.
http://developer.apple.com/mac/library/technotes/tn2005/tn2083.html#SECCODINGRECOMMENDATIONS
Found the problem - apparently launchd doesn't work properly with the old-style plist files. It loads OK, but won't run anything. Re-creating the above file as a new-style XML file solved the issue.
Related
I have a .m script that I've been running using Windows Task Scheduler, generally successfully, every 15 minutes for about a year (options: -automation -minimize -r remotedata -logfile logfile.txt;quit).
When I run the code manually in Matlab, everything behaves as expected.
However, when it is run as an automated script, it has two issues I can't resolve, that seem to indicate the code is not being executed the same way.
First, I have the following conditional:
~isempty(remoteData.Time(setdiff(1:end,ni))) which is terrible syntax, I know, but works just fine when I run the script manually. However, when it runs automated, it gives the error:
Error using setdiff (line 80) Not enough input arguments.
I corrected it to ~isempty(remoteData.Time(setdiff(1:height(remoteData),ni)))
but it made me curious.
Second, I have a webread function with a number of queries (see below) that executes normally when I have it open and hit "run", however, when running as an automation the dateutc query is ignored. This one is a bit more puzzling. Can anyone suggest a reason it might be failing to register, or how I might fix it? Debugging is difficult since it works as expected when I run it manually.
WUurl = 'http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php';
WUID = '***';
WUpwd = '***';
WUdateutc = datestr(datenum(webData.Time(WDNewest-newTimes+i))+7/24,'yyyy-mm-dd HH:MM:SS');
WUwindspeedmph = num2str(webData.WndSpd(WDNewest-newTimes+i)*0.62);
WUwinddir = num2str(webData.WndDir(WDNewest-newTimes+i));
WUtempf = num2str(webData.AirTmp(WDNewest-newTimes+i)*1.8+32);
WUrainin = num2str(webData.Rain(WDNewest-newTimes+i)/25.4*4);
WUdailyrainin = num2str(sum(webData.Rain(WDMidnight:WDNewest-newTimes+i))/25.4);
WUbaromin = num2str(webData.BarPress(WDNewest-newTimes+i)*.0295);
WUhumidity = num2str(webData.RelHum(WDNewest-newTimes+i));
gamma = log(webData.RelHum(WDNewest-newTimes+i)/100)+ ...
(17.67*webData.AirTmp(WDNewest-newTimes+i))/ ...
(243.5+webData.AirTmp(WDNewest-newTimes+i));
WUdewptf = num2str((243.5*gamma)/(17.67-gamma)*1.8+32); % Magnus formula estimation
WUsolarradiation = num2str(webData.NetRad_Wm2(WDNewest-newTimes+i));
WUsoiltempf = num2str(nanmean(webData{WDNewest,20:3:77})*1.8+32);
WUsoilmoisture = num2str(nanmean(webData{WDNewest,18:3:75}));
options = weboptions('Timeout',newTimes);
WU_debugging = webread(WUurl,...
'ID',WUID,...
'PASSWORD',WUpwd,...
'dateutc',WUdateutc,...
'windspeedmph',WUwindspeedmph,...
'winddir',WUwinddir,...
'tempf',WUtempf,...
'rainin',WUrainin,...
'dailyrainin',WUdailyrainin,...
'baromin',WUbaromin,...
'humidity',WUhumidity,...
'dewptf',WUdewptf,...
'solarradiation',WUsolarradiation,...
'soiltempf',WUsoiltempf,...
'soilmoisture',WUsoilmoisture,...
'action','updateraw',...
options);
I recall there being a Cocoa framework or AppleScript dictionary to check if an Application bundle with a specific name is installed at all, anywhere on the computer.
How do I do this? Either Cocoa, AppleScript, or command line are useful to me.
You should use Launch Services to do this, specifically the function LSFindApplicationForInfo().
You use it like so:
#import <ApplicationServices/ApplicationServices.h>
CFURLRef appURL = NULL;
OSStatus result = LSFindApplicationForInfo (
kLSUnknownCreator, //creator codes are dead, so we don't care about it
CFSTR("com.apple.Safari"), //you can use the bundle ID here
NULL, //or the name of the app here (CFSTR("Safari.app"))
NULL, //this is used if you want an FSRef rather than a CFURLRef
&appURL
);
switch(result)
{
case noErr:
NSLog(#"the app's URL is: %#",appURL);
break;
case kLSApplicationNotFoundErr:
NSLog(#"app not found");
break;
default:
NSLog(#"an error occurred: %d",result);
break;
}
//the CFURLRef returned from the function is retained as per the docs so we must release it
if(appURL)
CFRelease(appURL);
From the command line this seems to do it:
> mdfind 'kMDItemContentType == "com.apple.application-bundle" && kMDItemFSName = "Google Chrome.app"'
You can also use lsregister.
on doesAppExist(appName)
if (do shell script "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump | grep com.apple.Safari") ¬
contains "com.apple.Safari" then return true
end appExists
That's pretty fast and you can do it from other languages like Python quite easily. You would want to play around with what you grep to make it most efficient.
i have a new problem in image magick that look strange ..
i'm using mac osx snow leopard and i've installed image magick on it and it's working fine on command ..
but when i call it from the grails class like the following snippet it gives me
"Cannot run program "convert": error=2, No such file or directory"
the code is :-
public static boolean resizeImage(String srcPath, String destPath,String size) {
ArrayList<String> command = new ArrayList<String>(10);
command.add("convert");
command.add("-geometry");
command.add(size);
command.add("-quality");
command.add("100" );
command.add(srcPath);
command.add(destPath);
System.out.println(command);
return exec((String[])command.toArray(new String[1]));
}
private static boolean exec(String[] command) {
Process proc;
try {
//System.out.println("Trying to execute command " + Arrays.asList(command));
proc = Runtime.getRuntime().exec(command);
} catch (IOException e) {
System.out.println("IOException while trying to execute " );
for(int i =0 ; i<command.length; i++) {
System.out.println(command[i]);
}
return false;
}
//System.out.println("Got process object, waiting to return.");
int exitStatus;
while (true) {
try {
exitStatus = proc.waitFor();
break;
} catch (java.lang.InterruptedException e) {
System.out.println("Interrupted: Ignoring and waiting");
}
}
if (exitStatus != 0) {
System.out.println("Error executing command: " + exitStatus);
}
return (exitStatus == 0);
}
i've tried normal command like ls and it's ok so the problem is that grails can't find convert command itself.. is it a os problem or something?
(see lower for the answer)
I have run into the same problem. The issue appears to be something with Mac OS X specifically, as we have several Linux instances running without error. The error looks similar to the following:
java.io.IOException: Cannot run program "/usr/bin/ImageMagick-6.7.3/bin/convert /a/temp/in/tmpPic3143119797006817740.png /a/temp/out/100000726.png": error=2, No such file or directory
All the files are there, and in chmod 777 directories - and as you pointed out, running the exact command from the shell works fine.
My theory at this point is that imagemgick can not load some sort of library itself, and the "no such file" is in reference to an dylib or something along those lines.
I have tried setting LD_LIBRARY_PATH and a few others to no avail.
I finally got this working. Here is how I have it setup. I hope this helps.
The crux of the fix, for me, was I wrapped the 'convert' into a shell script, set a bunch of environment variables, and then call that shell script instead of convert directly:
(convertWrapper.sh)
export MAGICK_HOME=/usr/local/ImageMagick-6.7.5
export MAGICK_CONFIGURE_PATH=${MAGICK_HOME}/etc/ImageMagick:${MAGICK_HOME}/share/doc/ImageMagick/www/source
export PATH=${PATH}:${MAGICK_HOME}/bin
export LD_LIBRARY_PATH=${MAGICK_HOME}/lib:${LD_LIBRARY_PATH}
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:${MAGICK_HOME}/lib
export MAGICK_TMPDIR=/private/tmp
echo "$#" >> /private/tmp/m.log 2>&1
/usr/local/ImageMagick-6.7.5/bin/convert -verbose "$#" >> /private/tmp/m.log 2>&1
(convertWrapper.sh)
Additionally, the convert call was doing some rather complicated stuff, so I added the parameter '-respect-parenthesis' (which may or may not have had an effect).
I am not sure how much of the environment variable setting is needed as I was stabbing in the dark for a while, but since this is only for my development box...
You need to work out what your PATH is set to when you run a command from Java. It must be different to the one you have when running from the terminal.
Are you running Grails (via Tomcat?) as a different user? It might have a different path to your normal user.
you might want to try one of the Image Plugins that are part of the grails ecosystem
http://www.grails.org/ImageTools+plugin
the grails path when the app is running in the server is probably different from running java from the command line
I do so:
Put "convert" file to /usr/bin
Then add to Config.groovy:
gk {
imageMagickPath = "/usr/bin/convert"
}
Then in my ImageService.groovy:
import org.springframework.web.context.request.RequestContextHolder as RCH
[..]
def grailsApplication = RCH.requestAttributes.servletContext.grailsApplication
def imPath = grailsApplication.config.gk.imageMagickPath
def command = imPath + " some_properties"
def proc = Runtime.getRuntime().exec(command)
So this way you get command like: /usr/bin/convert some_properties
And it works, but don't forget to put file "convert" to you location and use it with this location.
I want to launch a browser and load a web page using Java's Runtime exec. The exact call looks like this:
String[] explorer = {"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE",
"-noframemerging",
"C:\\ ... path containing unicode chars ... \\Main.html"};
Runtime.getRuntime().exec(explorer);
In my case, the path contains "\u65E5\u672C\u8A9E", the characters 日本語.
Apparently it's a java bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4947220
My question is: is there a viable workaround that can be done solely using Java? It appears that it is possible to write a JNI library for this, but I'd like to avoid that if possible. I have tried URI-encoding the path as ascii and writing the commands to a batch file, without success.
At the mentioned Java bug page you will find a workaround that is reported to work using ProcessBuilder and wrapping the parameters in environment variables. Here is the source code from Parag Thakur:
String[] cmd = new String[]{"yourcmd.exe", "Japanese CLI argument: \ufeff\u30cb\u30e5\u30fc\u30b9"};
Map<String, String> newEnv = new HashMap<String, String>();
newEnv.putAll(System.getenv());
String[] i18n = new String[cmd.length + 2];
i18n[0] = "cmd";
i18n[1] = "/C";
i18n[2] = cmd[0];
for (int counter = 1; counter < cmd.length; counter++)
{
String envName = "JENV_" + counter;
i18n[counter + 2] = "%" + envName + "%";
newEnv.put(envName, cmd[counter]);
}
cmd = i18n;
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
env.putAll(newEnv);
final Process p = pb.start();
Create a .bat/.sh file. Write your commands to that file and execute it. Make sure that you have changed the code page to unicode in case of windows(chcp 65001).
For example to execute the below command in windows:
String[] command ={"C:\\aconex\\学校\\mysql\\bin\\mysql", "-esource", "大村箕島a\\data.sql"};
Create a temp file called temp.bat and execute with the Runtime.getRuntime().exec
temp.bat
chcp 65001
C:\aconex\学校\mysql\bin\mysql -esource 大村箕島a\data.sql
These are the two solutions I considered, each of which are more or less workarounds:
Create a temp html redirect file which will redirect the browser to the proper page.
Note that IE will expect unencoded unicode for local files, while other browsers may accept only uri-encoded file paths
Use the short filename for the windows file. It won't contain unicode characters.
We've been using a JNI to start processes from Java for years. Neither Runtime.exec or ProcessBuilder will work, and it seems unlikely that they will fix this, given how long it's been already.
However, you should be able to work around the issue by using the input stream, a socket, or environment variables to pass parameters. If you don't have direct control over the executable, you'll have to make a wrapper.
You could use JNA. With version 3.3.0 or later call CreateProcess:
WinBase.PROCESS_INFORMATION.ByReference processInfo =
new WinBase.PROCESS_INFORMATION.ByReference();
WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
String command = "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE " +
"-noframemerging \"C:\\\u65E5\u672C\u8A9E\\Main.html\"";
if (!Kernel32.INSTANCE.CreateProcess(
null, // Application name, not needed if supplied in command line
command, // Command line
null, // Process security attributes
null, // Thread security attributes
true, // Inherit handles
0, // Creation flags
null, // Environment
null, // Directory
startupInfo,
processInfo))
{
throw new IllegalStateException("Error creating process. Last error: " +
Kernel32.INSTANCE.GetLastError());
}
// The CreateProcess documentation indicates that it is very important to
// close the returned handles
Kernel32.INSTANCE.CloseHandle(processInfo.hThread);
Kernel32.INSTANCE.CloseHandle(processInfo.hProcess);
long pid = processInfo.dwProcessId.longValue();
Redirecting output from the child process is a bit harder but not impossible.
I think you can use Apache Commons Exec library or ProcessBuilder to give a try;)
I need to be able to change a user's password from a cron task or from an ssh session. Is there an easy way to do that with a bash script? If not, what's the easiest way to do it in Cocoa?
Apple introduced CSIdentitySetPassword API in Mac OS 10.5 that allows to change password as follows:
#import <Collaboration/Collaboration.h>
AuthorizationRef authRef = NULL; // You have to initialize authRef
CBIdentityAuthority *authority = [CBIdentityAuthority defaultIdentityAuthority];
CSIdentityRef identity = [CBIdentity identityWithName:user authority:authority].CSIdentity;
if (CSIdentityGetClass(identity) == kCSIdentityClassUser) {
CSIdentitySetPassword(identity, (__bridge CFStringRef)newPassword);
CSIdentityCommit(identity, authRef, NULL);
}
AuthenticationRef can be initialized like int this response.
Use the passwd shell command.