Posted on 03-03-2021 02:08 AM
Hi All!
I am trying to run a script to check if our PaperCut User Client application is actually running.
I was using the below script on my machine and it returned the results as expected.
*#!/bin/sh
SERVICE=PCClient
if ps ax | grep -v grep | grep -v $0 | grep $SERVICE > /dev/null
then
echo "$SERVICE service running, everything is fine"
else
echo "$SERVICE is not running"
fi*
But when I put this into JAMF as a policy to run the script, it falls over and returns this.
Script result: grep: Support/JAMF/tmp/Check: No such file or directory
grep: if: No such file or directory
grep: PCClient: No such file or directory
grep: is: No such file or directory
grep: running: No such file or directory
PCClient is not running
I assume this is because of where it is trying to run the file from. So I did some digging on here to try and find a script I could add to, to force it to run as the logged-in user.
I found the one below and tried to edit it to work, but it gets unexpected end of file, and cannot work out why (i am new to mac and scripting so apologies if it's an obvious oversight!)
#!/bin/bash
loggedInUser=$(stat -f%Su /dev/console)
loggedInUID=$(id -u "$loggedInUser")
if [[ "$loggedInUser" != "root" ]] || [[ "$loggedInUID" -ne 0 ]]; then
cat << EOF > /private/tmp/script.sh
#!/bin/bash
service=PCClient
if ps ax | grep -v grep | grep -v $0 | grep $SERVICE > /dev/null
then
echo "$SERVICE service running, everything is fine"
else
echo "$SERVICE is not running"
exit 0
EOF
else
echo "No user logged in. Can't run as user, so exiting"
exit 0
fi
if [ -e /private/tmp/script.sh ]; then
/bin/chmod +x /private/tmp/script.sh
/bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" "/private/tmp/script.sh"
sleep 2
echo "Cleaning up..."
/bin/rm -f "/private/tmp/script.sh"
else
echo "Oops! Couldn't find the script to run. Something went wrong!"
exit 1
fi
All help gratefully received.
Matt
Solved! Go to Solution.
Posted on 03-08-2021 01:20 PM
Hey @mgoodall When launchctl list
is run as root as it would be from a Jamf policy, you get any processes that are typically being run in a root context. When you run the same command as a user, whether an admin or standard account, you get a list of user level launchd jobs. Essentially it's the difference between LaunchDaemons and LaunchAgents. I don't use the PaperCut agent, but my guess is the process runs in the user space, meaning it's run as a LaunchAgent.
Given this, you have to adjust your commands to tell your script to run the launchctl list
command as the logged in user. You could try using the same syntax you mentioned previously, such as `su "$currentuser" -c "launchctl list | grep 'biz.papercut.pcng.client.'" to see if it works.
Another method I like to use is the launchctl asuser
syntax.
#!/bin/sh
logged_in_user=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ {print $3}')
logged_in_uid=$(id -u "$logged_in_user")
result=$(/bin/launchctl asuser "$logged_in_uid" sudo -iu "$logged_in_user" /bin/launchctl list | grep "biz.papercut.pcng.client.")
<rest of your script here>
Posted on 03-03-2021 03:08 AM
So I found that I had an unwanted space at the end of EOF, which I removed.
The CAT command is now creating the script.sh file as expected but it then errors and removes it (as expected)
mgoodall@Matts-MacBook-Pro ~ % /Users/mgoodall/Documents/LinuxScripts/test4.sh
usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
is not running
Cleaning up...
Ive got a copy of the script.sh file that it creates and it looks like it's removing the tag for the variable $SERVICE.. and putting in grep -v /Users/mgoodall etc rather than grep $SERVICE
Below is what is being output to the script.sh file
#!/bin/bash
SERVICE=PCClient
if ps ax | grep -v grep | grep -v /Users/mgoodall/Documents/LinuxScripts/test4.sh | grep | grep > /dev/null
then
echo " service running, everything is fine"
else
echo " is not running"
exit 0
And below is what I was expecting it to output to the script.sh file.
#!/bin/sh
SERVICE=PCClient
if ps ax | grep -v grep | grep -v $0 | grep $SERVICE > /dev/null
then echo "$SERVICE service running, everything is fine"
else echo "$SERVICE is not running"
fi
What am i missing here?
Posted on 03-03-2021 04:06 AM
Ok, so I got the script to work.. but it still fails when created in JAMF as a policy with the same error as my first post.
I have also tried to create it as an extension attribute so that it can be seen when looking at the device in JAMF, but I don't seem to be getting any results back.
What's the best way to implement this?
#!/bin/bash
loggedInUser=$(stat -f%Su /dev/console)
loggedInUID=$(id -u "$loggedInUser")
if [[ "$loggedInUser" != "root" ]] || [[ "$loggedInUID" -ne 0 ]]; then
cat << EOF > /private/tmp/script.sh
#!/bin/bash
#SERVICE=PCClient
if ps ax | grep -v grep | grep -v $0 | grep PCClient > /dev/null
then
echo "PCClient service running, everything is fine"
else
echo "PCClient is not running"
exit 0
fi
EOF
else
echo "No user logged in. Can't run as user, so exiting"
exit 0
fi
if [ -e /private/tmp/script.sh ]; then
/bin/chmod +x /private/tmp/script.sh
/bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" "/private/tmp/script.sh"
sleep 2
echo "Cleaning up..."
/bin/rm -f "/private/tmp/script.sh"
else
echo "Oops! Couldn't find the script to run. Something went wrong!"
exit 1;
fi
Posted on 03-03-2021 12:42 PM
The script below is based off of the first script in your original post. I tested it by looking for BBEdit and it worked. (Adding the c
option to the ps
command will only display the executable name, so you don't need the two grep -v
commands.)
#!/bin/bash
currentUser=$(stat -f%Su /dev/console)
SERVICE=PCClient
if [[ $(sudo -u "$currentUser" ps acx | grep $SERVICE) ]]; then
echo "$SERVICE service running, everything is fine"
else
echo "$SERVICE is not running"
fi
Also, when you add code to a post, you can wrap it in ``` to make it easier to read.
Posted on 03-08-2021 07:53 AM
Thanks so much for your response and for helping with my code.
I found that this actually won't work due to the service name.. but I found an alternative that works fine from my PC.
#!/bin/bash
#RUN LAUNCHCTL TO CHECK FOR PAPERCUT PROCESS
result=$(launchctl list | grep biz.papercut.pcng.client.14444)
if [[ "$result" == *biz.papercut.pcng.client.14444* ]] ; then
echo "PaperCut Client is running"
exit 0
else
#RUN PCClient.app
open -a /Applications/PCClient.app
#currentuser=`stat -f "%Su" /dev/console`
#su "$currentuser" -c "open -a /Applications/PCClient.app"
sleep 10
#START CHECK AGAIN FOR PAPERCUT PROCESS
result=$(launchctl list | grep biz.papercut.pcng.client.14444)
if [[ "$result" == *biz.papercut.pcng.client.14444* ]] ; then
echo "PaperCut Client is running"
else
echo "AGHH SOMETHING IS BROKEN"
exit 1
fi
fi
The issue I am having is that when I put this as a script into JAMF and it runs, I get back "Script result: The application /Applications/PCClient.app cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-10826 "kLSNoLaunchPermissionErr: User doesn't have permission to launch the app (managed networks)" UserInfo={_LSFunction=_LSLaunchWithRunningboard, _LSLine=2508, NSUnderlyingError=0x7fae4bd0fe50 {Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x7fae4bd10610 {Error Domain=OSLaunchdErrorDomain Code=125 "Domain does not support specified action" UserInfo={NSLocalizedFailureReason=Domain does not support specified action}}}}}
However, if u run this script, which checks a different location, I get results back that it was successful.. still using the open -a command, which I have tested as a standard user, and it works.
The
#currentuser=`stat -f "%Su" /dev/console`
#su "$currentuser" -c "open -a /Applications/PCClient.app"
was added only to see if forcing it to run as the current user would fix it.. it didn't.
This is to basically check that the PaperCut UserClient is running and if it's not, tell it to open.
Once it is opened I am then using an extension attribute to display the time and date that it was last opened. This app is to run when the user logs in but like most places people don't reboot or shutdown very often.
Also, the app, if not connected to the corporate network will time out and close... so I need to have a script to tell it to open if it's not open or when they return to the site, they cannot print..
HELP!
Posted on 03-08-2021 11:11 AM
So, i found an error in what i was looking for in LaunchCTL List..
#!/bin/sh
result=$(launchctl list | grep biz.papercut.pcng.client.14444)
the 14444 changes on each machine, so i changed the script to looking for everthing else including the last . as the other service that appers in the list is not active and is there all the time.
It again works on my machine and if I echo the results variable I get a result when the app is open and nothing when the app is closed.. GREAT making progress!
NO! on every machine the script is set to run I am getting a failure.. which is how I feel after a day of trying to get this to work!
Posted on 03-08-2021 01:20 PM
Hey @mgoodall When launchctl list
is run as root as it would be from a Jamf policy, you get any processes that are typically being run in a root context. When you run the same command as a user, whether an admin or standard account, you get a list of user level launchd jobs. Essentially it's the difference between LaunchDaemons and LaunchAgents. I don't use the PaperCut agent, but my guess is the process runs in the user space, meaning it's run as a LaunchAgent.
Given this, you have to adjust your commands to tell your script to run the launchctl list
command as the logged in user. You could try using the same syntax you mentioned previously, such as `su "$currentuser" -c "launchctl list | grep 'biz.papercut.pcng.client.'" to see if it works.
Another method I like to use is the launchctl asuser
syntax.
#!/bin/sh
logged_in_user=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ {print $3}')
logged_in_uid=$(id -u "$logged_in_user")
result=$(/bin/launchctl asuser "$logged_in_uid" sudo -iu "$logged_in_user" /bin/launchctl list | grep "biz.papercut.pcng.client.")
<rest of your script here>
Posted on 03-09-2021 02:26 AM
Hi @mm2270
Thanks, makes perfect sense just after hours of looking i must have gone blind!
Tested and working.. Thank you for your help!
Matt
Posted on 03-09-2021 07:52 AM
So this is my final script
#!/bin/bash
#RUN LAUNCHCTL TO CHECK FOR PAPERCUT PROCESS
logged_in_user=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ {print $3}')
logged_in_uid=$(id -u "$logged_in_user")
result=$(/bin/launchctl asuser "$logged_in_uid" sudo -iu "$logged_in_user" /bin/launchctl list | grep "biz.papercut.pcng.client.")
if [[ "$result" == *biz.papercut.pcng.client.* ]] ; then
echo "PaperCut Client is running"
exit 0
else
#RUN PCClient.app
open -a /Applications/PCClient.app
sleep 10
#START CHECK AGAIN FOR PAPERCUT PROCESS
result=$(/bin/launchctl asuser "$logged_in_uid" sudo -iu "$logged_in_user" /bin/launchctl list | grep "biz.papercut.pcng.client.")
if [[ "$result" == *biz.papercut.pcng.client.* ]] ; then
echo "PaperCut Client is running"
else
echo "AGHH SOMETHING IS BROKEN"
exit 1
fi
fi
Which in 99% of cases is working.
What I am finding is that on some machines, ive narrowed it down to High Serria when the script is run, i am getting the following error.
LSOpenURLsWithRole( ) failed for the applicaiton /Applications/PCClient.app with error -610
Is this because the part of the script that is telling the app to open
open -a /Applications/PCClient.app
is also being run as root and not as the logged-in user? How would i script it to run as the logged-in user?
Posted on 03-09-2021 07:58 AM
I use the following to open an app as the user:
currentUser=$(stat -f%Su /dev/console)
sudo -u "$currentUser" open -a /Applications/PCClient.app
Posted on 05-24-2021 06:07 PM
@skeenan07 could you use this to run something like the below text?
currentUser=$(stat -f%Su /dev/console)
"$currentUser" diskutil resetUserPermissions / `id -u`
Also apologies in advance as I'm still new to learning scripting.
Posted on 05-24-2021 09:00 PM
You can also use Python ObjC Bridge to leverage macOS APIs like NSWorkspace
, example:
>>> from AppKit import NSWorkspace
>>> procs = []
>>> workspace = NSWorkspace.sharedWorkspace()
>>> running_apps = workspace.runningApplications()
>>> for app in running_apps:
... procs.append(app.localizedName())
...
>>> print(procs)
This will grab every localized name of every process running in the current user space
Posted on 05-25-2021 04:42 AM
@daniel_ross To run a command as the user, you'll need to use sudo. For the command you've mentioned, it would look like the following:
currentUser=$(stat -f%Su /dev/console)
sudo -u "$currentUser" diskutil resetUserPermissions / $(id -u)
Also, note that I've changed the `id -u` to $(id -u).
Posted on 09-17-2021 06:18 AM
While I needed a solution to run as Root and not the end user, I used this post as a starting point and put my own spin on it. Posting my snippet of code that it may be helpful to someone in the future.
This has worked very consistently for me.
## Variables
PCClientPID=$(ps -ax | grep PCClient | grep -v grep | awk '{print $1}')
## kill PCClient process if running
if (test -z $PCClientPID); then
echo "PCClient not running";
elif (test -n $PCClientPID); then
kill $PCClientPID
fi
Posted on 09-18-2021 11:30 AM
Another great way to do this is with the `NSRunningApplication` API and you can access it via pyobjc bridge. Example:
>>> from Cocoa import NSRunningApplication
>>>
>>> app = NSRunningApplication.runningApplicationsWithBundleIdentifier_("com.brave.Browser")
>>> if app:
... print("app is running")
... else:
... print("app is not running")
...
app is running
You can feed this API the bundle ID of the app and it will return `True` or `False` if it is running or not