views:

1425

answers:

2

I am running a jar file from within an app bundle on Mac OS X Leopard. I need to pass into the jar a parameter. The parameter is the absolute path of the file which called the app bundle. I have my short bash script below. I know $0 gives the absolute path to the app bundle itself.

Does anyone know how to store in a variable the path I need (CALLERPATH below)? The current script listed works fine if another script calls it (find caller script in the reply from Dennis), but does not work the same when I double-click on "file.xyz".

Script 1

#!/bin/bash
echo $0
echo $_
echo $(dirname $0)
echo $(basename $0)
echo $PWD
echo "$@"
echo $PPID
echo "My PPID echo"
myPPID=$PPID echo $(ps -p $myPPID -o args=)
BASEDIR=`dirname "$0"`
echo "CallerPath Output 1"
callerpath="$(/bin/ps -p $PPID -o args=)"
echo -e "$callerpath\n"
echo "Caller Path Output 2"
callerpath="${callerpath#/bin/bash *}"
echo -e "$callerpath\n"
echo "Final Caller Path"
callerpath="${callerpath%/*}"
echo -e "$callerpath\n"
exec java \
-jar "$BASEDIR/../Resources/Java/myJar.jar" "$callerpath"

Output 1

9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] /Applications/appBundle.app/Contents/MacOS/myScript
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] /Applications/appBundle.app/Contents/MacOS/myScript
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] /Applications/appBundle.app/Contents/MacOS 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] myScript
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] / 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] -psn_0_766139 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] 63 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] My PPID echo 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] ps: Invalid process id: -o 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] ps: illegal argument: args= 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] usage: ps [-AaCcEefhjlMmrSTvwXx] [-O fmt | -o fmt] [-G gid[,gid...]] 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496]           [-g grp[,grp...]] [-u [uid,uid...]] 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496]           [-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]] 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496]        ps [-L] 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] CallerPath Output 1 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] Caller Path Output 2 
9/25/09 3:54:42 PM [0x0-0xbb0bb].MyApp[1496] Final Caller Path

Script 2

#!/bin/bash
echo $0
echo $_
echo $(dirname $0)
echo $(basename $0)
echo $PWD
echo "$@"
echo $PPID
echo "My PPID export"
export myPPID=$PPID
echo $(ps -p $myPPID -o args=)
BASEDIR=`dirname "$0"`
echo "CallerPath Output 1"
callerpath="$(/bin/ps -p $PPID -o args=)"
echo -e "$callerpath\n"
echo "Caller Path Output 2"
callerpath="${callerpath#/bin/bash *}"
echo -e "$callerpath\n"
echo "Final Caller Path"
callerpath="${callerpath%/*}"
echo -e "$callerpath\n"
exec java \
-jar "$BASEDIR/../Resources/Java/myJar.jar" "$callerpath"

Output 2

9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] /Applications/appBundle.app/Contents/MacOS/myScript
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] /Applications/appBundle.app/Contents/MacOS/myScript
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] /Applications/appBundle.app/Contents/MacOS 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] myScript
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] / 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] -psn_0_790721 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] 63 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] My PPID export 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] CallerPath Output 1 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] Caller Path Output 2 
9/25/09 4:02:40 PM [0x0-0xc10c1].MyApp[1561] Final Caller Path
A: 

It's a bit of a kludge, but here goes:

First, your tags include "bash", but your shebang is for /bin/sh. I'm assuming Bash.

First caller:

#!/bin/bash
/home/username/dirONE/calltest a b c

Next calltest:

#!/bin/bash
# echo some stuff to get our bearings
echo $0
echo $_                                  # should be the same as $0
echo $(dirname $0)
echo $(basename $0)
echo $PWD
echo "$@"
echo $PPID                               # parent process ID
# start making $callerpath, if there are spaces in a dirname or script name, they should be preserved
callerpath="$(ps -p $PPID -o args=)"     # get the command name of the parent (it may have args after it)
callerpath="${callerpath#/bin/bash *}"   # strip /bin/bash from the beginning
callerpath="${callerpath%/*}"            # like dirname, but removes the args, too
echo "$callerpath"

Now to run the test:

$ cd /home/username/dirTHREE
$ /home/username/dirTWO/caller 1 2 3
/home/username/dirONE/calltest
/home/username/dirONE/calltest
/home/username/dirONE
calltest
/home/username/dirTHREE
a b c
32674
/home/username/dirTWO
Dennis Williamson
This test code returns simply a "/" character as my caller path. I do not know why, because I am not framiliar with all the bash syntax
Ken
What does `ps -p $PPID -o args=` produce (include it on a line by itself in the "calltest" script)?
Dennis Williamson
I initially tried to just copy the "callpath=" lines into my above script. But when I ran it as you wrote your post, as two scripts, it gives me ": command not foundltest: line 9:"...maybe there is a syntax error? And were you assuming this was a script calling the bundle? As clarification, my app bundle is being called from a file of my own registered file extension. So i double click "file.xyz", launch manager knows my app is the owner, and gives me the abs path to that file. i dont know how mac handles that path (the "open" command in windows usually has "%1" as the abs path).
Ken
I cut out the comments and such, so the error line was the ps -p $PPID -o args=
Ken
$PWD placed in my script above returns "/"...probably because my app bundle resides in /Applications. The "$@" returns "-psn_0_" with a random number after the last underscore. The $PPID doesnt echo anything to the screen.
Ken
You need to change your shebang to "`#!/bin/bash`" if you haven't. Your `/bin/sh` may not have the $PPID environment variable. "And were you assuming this was a script calling the bundle?" I am assuming that the script in your question is called by something. That something is its parent. The parent's process ID is $PPID. What do `echo $PPID` and `ps -p $PPID -o args=` produce at a Bash prompt?
Dennis Williamson
I changed the shebang as you said to a Bash prompt. I do get a number for $PPID, which of course changes every run. but still get the command not found errors when trying to set callerpath.
Ken
Please add to your question post your test script which includes the callerpath lines and add a comment to the line which produces the error.
Dennis Williamson
I posted in my question both scripts and the output from the terminal. Thank you for your continued effort on this issue.
Ken
First try: `dos2unix yourscriptname`. If that fixes it then ignore this>>> I think you're running into a Unicode or other character encoding or a line ending problem. At a Bash prompt, try 1) pasting in the line that has the `ps` in it, 2) hand entering that same line, 3) if you get errors on both of those try hand typing: `test=$(ls)` If you get an error on #1 but not #2 then it's an encoding or line-ending problem. If both have errors, but not #3 then it's something else. One of the reasons I think it's a line ending problem is that the error messages appear to have overwritten themselves.
Dennis Williamson
You were correct in that there was extra space at the end of some lines in the calltest script. The calltest script now works. I reposted in my question the current script in my app bundle and the console output. Nothing is being echoed for the caller path and no errors reported. I do not know who technically is the parent process when I double click "file.xyz". Would the parent be the file itself, which isnt a script, or would the parent be the Launch Manager and that somehow complicates things? I feel this is very close, thanks again for your continued input.
Ken
Change all your `echo "$callerpath"` lines to `echo -e "$callerpath\n"` and add `ps -p $PPID -o args=` under `echo $PPID` and post the result. (Those `echo "$callerpath"` lines should have produced blank lines in the output if `$callerpath` is null, rather than nothing at all.) I'm particularly interested in seeing the output of `ps`. Please also run that `ps` command at a shell prompt and post its output.
Dennis Williamson
The script code is updated as well as the output, and the ps command from the terminal by itself. The output did not change when double-clicking the file (only the psn changed). Odd that the "ps -p $PPID -o args=" produced nothing in the output.
Ken
Everywhere there's a `ps` add its full path, likely `/bin`, so they look like `/bin/ps...` - you can do `type -a ps` or `which ps` to find out where it is.
Dennis Williamson
using the "type -a ps" command in the app bundle script returns "ps is /bin/ps". Still no output when changing to "/bin/ps -p $PPID -o args=". I know this is probably getting frustrating haha.
Ken
After days of researching this, I may have abandon this route. All over now I am seeing that "Java + SWT + Mac OS X app bundle + getting the caller path = pretty much impossible". They say Apple is ALL event based and you cannot get file path parameters through the command line in the context that i want it (only through an event handle). I have some ideas for work around programmatically I may have to live with until a bridge to apple events is available again. Once again thank you for all your attempts.
Ken
Change the line under `echo $PPID` to `echo $(ps -p $PPID -o args=)` and see what it prints out. It doesn't make any sense that `basename` and `dirname` produce output and `ps` doesn't. You might even experiment with other executables like `ls`, `date`, `uname` or `tty`. I wonder if there's another character encoding or stray character problem. It seems too close for me to be willing to quit. I love a good puzzle.
Dennis Williamson
I am willing to keep going to solve it haha. I updated the script again and output in the post. Its interesting that echo $(ps) produces an output and echo $(ps -p $PPID -o args=) produces no output. Maybe the script cannot access the parent? Not sure.
Ken
Try `myPPID=$PPID echo $(ps -p $myPPID -o args=)` (all on one line - note "my" in two places). If that doesn't work, try `export myPPID=$PPID` on one line, then the next line: `echo $(ps -p $myPPID -o args=)`
Dennis Williamson
Both scripts and outputs are posted above. First one provided an error in syntax, the other no output at all.
Ken
I will be heading out shortly for the weekend and we can continue this saga monday if you like. can post some suggestions you come up with and i will try them out then. have a good weekend dennis.
Ken
Go back and test this stuff (the various iterations we've gone through) using the "caller" and "calltest" scripts in a Terminal instead of from your app bundle, making sure to fix the line endings and trying the variations on `ps`. Skip the myPPID tests. Also, change your echoes to wrap some text around the arguments, for example: `echo "+++$(ps -p $myPPID -o args=)---"` and `echo "+++${callerpath}---"` (note the removal of the `-e` and `\n` and addition of `{}`).
Dennis Williamson
+1  A: 

I have a Mac, so I cannot use the $(readlink -f $0) trick. Here is my solution, please test it against your system as I don't have a Linux machine handy:

# Get absolute path of the script
dir=`dirname $0`            # The directory where the script is 
pushd "$dir" > /dev/null    # Go there
CALLERPATH=$PWD             # Record the absolute path
popd > /dev/null            # Return to previous dir

echo $CALLERPATH

How does it work?

The strategy is 1) get the dir name, 2) cd to it, and 3) record the $PWD, which is always in absolute path format.

Hai Vu
I do not have a Linux system either, I am running this script on Mac OS X Leopard. If you push $0 onto the stack and navigate there, then store the $PWD, you just get the directory of app bundle again. I need the path of the file which called the app bundle.
Ken