Script to kill process before re-installing app

fabian_ulmrich
Contributor
Contributor

Hi guys,

I am pretty new with scripting and really don't have an idea how to solve my problem. And as I learned from JNUC '13 - never script alone :) Hope you can help!

Unfortunately I have some Apps running with the wrong permissions, meaning kids can write into the package content to run other apps like Terminal or so. Now I wrote a script to see if the application is existent, if yes the script should check if the process is running, if yes kill process, mv the corrupt app to Utilities Folder (totally blocked for my students) and re-install a fixed version via policy trigger. So far everything works fine if I declare my variables in the script, but I would like to use it a little bit advanced by using the JAMF script parameters, so I could use the one script for similar problems.

May you guys could check my code and let me know what I am doing wrong. The Script always stops working before it mv the app, equal if App is running or not :(

Thanks in advance!
Fabian

#!/bin/bash
## Bavarian International School e.V. - Fabian Ulmrich
## Check for specified Application Folder - if exits move Folder
#####################################################################

# HARDCODED VALUES ARE SET HERE
#specified AppFolder
appdir=""
#Process to look for
process=""
#specified Policy Trigger
trigger=""

## Variables
if [ "$4" != "" ] && [ "$appdir" == "" ]; then
    appdir=$4
fi

if [ "$5" != "" ] && [ "$process" == "" ]; then
    process=$5
fi

if [ "$6" != "" ] && [ "$trigger" == "" ]; then
    trigger=$6
fi

apputil="/Applications/Utilities/"
logfile="/private/var/log/AppMove.log"
logdate=`date "+Log: %d.%m.%Y - %H:%M:%S"`
jamf="/usr/sbin/jamf"


## Creating Log
/usr/bin/touch "/private/var/log/AppMove.log" >> "${logfile}"
/bin/echo "${logdate}" >> "${logfile}"
/bin/echo "Logfile created..." >> "${logfile}"



## Check if values are set for Script in Policy Script Details
if [ "$appdir" == "" ]; then
    /bin/echo "Error:  No appdir value is specified."
    exit 1
fi

if [ "$process" == "" ]; then
    /bin/echo "Error:  No process value is specified."
    exit 1
fi

if [ "$trigger" == "" ]; then
    /bin/echo "Error:  No trigger value is specified."
    exit 1
fi


## Script
if [ -d "${appdir}" ]; then

        /bin/echo "Check if specific App is running" >> "${logfile}"
        ps aux | grep "${process}" | grep -v grep > /dev/null
        if [ $? -eq 0 ]; then
            /bin/echo "Stopping process: $process" >> "${logfile}"
            /bin/ps aux | grep "${process}" | grep -v grep | awk '{print$2}' | xargs kill -9
        else
            /bin/echo "No process ${process} running - continue script" >> "${logfile}"   
        fi

        sleep 5

        /bin/echo "Moving Folder to /Applications/Utilities" >> "${logfile}"
        /bin/mv "${appdir}" "${apputil}"

        /bin/echo "Installing fixed version of corrupt application via JAMF policy"  >> "${logfile}"
        "${jamf}" policy -trigger "${trigger}" >> "${logfile}"

else
        /bin/echo "$appdir is not an installed Application on this Computer" >> "${logfile}"
fi

exit 0
2 ACCEPTED SOLUTIONS

mm2270
Legendary Contributor III

@fabsen83][/url][/url][/url

See if you can incorporate this. In short, using ps axc to look for only the process name as it shows up in something like the Application Switcher (eliminates need for grep -v's), but then using mdfind to locate the full path to the app.

#!/bin/bash

process="$4"
apputil="/Applications/Utilities/"

processrunning=$( ps axc | grep "${process}" )
if [ "$processrunning" != "" ]; then
    echo "$process found running"
    appdir=$(mdfind -onlyin /Applications/ "kMDItemKind == 'Application' && kMDItemDisplayName == '$process'")
    echo "App directory is: ${appdir}"
    /bin/echo "Stopping process: $process"
    killall "${process}"
    sleep 5
    /bin/echo "Moving application ${appdir} to ${utildir}"
    /bin/mv "${appdir}" "${utildir}"
else
    /bin/echo "No process ${process} running - continue script"
    /bin/echo "Moving application ${appdir} to ${apputil}"
    /bin/mv "${appdir}" "${apputil}"
fi

This seemed to work for me in some limited testing. Hopefully it will work for you.

View solution in original post

nessts
Valued Contributor II

or like i said pgrep
(maverick) ~ 19 11:20am% pgrep firefox
83051
just returns a process id

and if you are using killall why not just say killall or pkill and move the app? killall and pkill wont kill anything its not supposed to kill.

you could say

killall $process
if [ $? -eq 1 ]; then echo "$process found running, and killed it"
fi
appdir=$(mdfind -onlyin /Applications/ "kMDItemKind == 'Application' && kMDItemDisplayName == '$process'")
echo "App directory is: ${appdir}"
/bin/echo "Moving application ${appdir} to ${utildir}"
/bin/mv "${appdir}" "${utildir}"

View solution in original post

14 REPLIES 14

mm2270
Legendary Contributor III

Can you give an example of what you're entering for the "appdir" parameter? My first guess is it may be not seeing the correct application path to do the move.
Also, any errors in the policy log that would give a hint on the issue?

fabian_ulmrich
Contributor
Contributor

Thanks for your reply - For exampe I am using the path /Applications/appname.app
Unfortunately I don't have any errors in the policy log.

mm2270
Legendary Contributor III

OK, that's what I figured, but wanted to be sure. Is the script correctly killing the open application (if its open)? Is the issue that it just won't move the app into Utilities? Will it run the jamf policy afterwards, or does it simply stop after the kill command?

Edit: One other question. Are you using http/s for your CasperShare, or is it set up as SMB/AFP?

fabian_ulmrich
Contributor
Contributor

It kills the application and will stop afterwards. What I am wondering is, although the application is not open it echos "Stopping process bla bla.." The mv and trigger is not working at all.

fabian_ulmrich
Contributor
Contributor

We are using AFP and have https active as well.

Josh_S
Contributor III

I suspect that your kill statement is actually killing this script as well as the process you're trying to kill. As part of your "ps" lines, try also excluding the name of this script. The script is getting passed the process name as a parameter and, for the same reason you have to use grep -v grep, you need to make sure you aren't killing your own process.

ps aux | grep "${process}" | grep -v grep | grep -v script.sh
...
/bin/ps aux | grep "${process}" | grep -v grep | grep -v script.sh | awk '{print$2}' | xargs kill -

fabian_ulmrich
Contributor
Contributor

When I use it without JAMF parameters it works fine. It looks like, the problem is to check wether the process is running or not, that's why I tried to if command the last returned value.

See this one works fine!

#!/bin/sh
## Variables
appdir="/Applications/VLC.app" #specified AppFolder
apputil="/Applications/Utilities/"
process="VLC" #Process to look for
logfile="/private/var/log/AppMove.log"
logdate=`date "+Log: %d.%m.%Y - %H:%M:%S"`
jamf="/usr/sbin/jamf"
trigger="vlc"


## Creating Log
/usr/bin/touch "/private/var/log/AppMove.log" >> "${logfile}"
/bin/echo "${logdate}" >> "${logfile}"
/bin/echo "Logfile created..." >> "${logfile}"


## Script
if [ -d "${appdir}" ]; then

        /bin/echo "Check if specific App is running" >> "${logfile}"
        if ps aux | grep "${process}" | grep -v grep > /dev/null
        then
            /bin/echo "Stopping process: $process" >> "${logfile}"
            /bin/ps aux | grep "${process}" | grep -v grep | awk '{print$2}' | xargs kill -9
        else
            /bin/echo "No process ${process} running - continue script" >> "${logfile}"   
        fi

        sleep 5

        /bin/echo "Moving App to /Applications/Utilities" >> "${logfile}"
        /bin/mv "${appdir}" "${apputil}"

        /bin/echo "Installing fixed version of App via JAMF policy"  >> "${logfile}"
        "${jamf}" policy -trigger "${trigger}" >> "${logfile}"      

else
        /bin/echo "$appdir is not an installed Application on this Computer" >> "${logfile}"
fi

exit 0

nessts
Valued Contributor II

look at using pgrep or pkill or killall somebody has already done some of that work for you.

fabian_ulmrich
Contributor
Contributor

@Josh_S

That's what I figured out myself by writing the output into an txt. Than I tried to grep -v the script as well, it worked once but with a different app it didn't work again. Also it did not work by using /dev/null :/

It drives me crazy, but it's also fun :)

mm2270
Legendary Contributor III

@fabsen83][/url][/url][/url

See if you can incorporate this. In short, using ps axc to look for only the process name as it shows up in something like the Application Switcher (eliminates need for grep -v's), but then using mdfind to locate the full path to the app.

#!/bin/bash

process="$4"
apputil="/Applications/Utilities/"

processrunning=$( ps axc | grep "${process}" )
if [ "$processrunning" != "" ]; then
    echo "$process found running"
    appdir=$(mdfind -onlyin /Applications/ "kMDItemKind == 'Application' && kMDItemDisplayName == '$process'")
    echo "App directory is: ${appdir}"
    /bin/echo "Stopping process: $process"
    killall "${process}"
    sleep 5
    /bin/echo "Moving application ${appdir} to ${utildir}"
    /bin/mv "${appdir}" "${utildir}"
else
    /bin/echo "No process ${process} running - continue script"
    /bin/echo "Moving application ${appdir} to ${apputil}"
    /bin/mv "${appdir}" "${apputil}"
fi

This seemed to work for me in some limited testing. Hopefully it will work for you.

nessts
Valued Contributor II

or like i said pgrep
(maverick) ~ 19 11:20am% pgrep firefox
83051
just returns a process id

and if you are using killall why not just say killall or pkill and move the app? killall and pkill wont kill anything its not supposed to kill.

you could say

killall $process
if [ $? -eq 1 ]; then echo "$process found running, and killed it"
fi
appdir=$(mdfind -onlyin /Applications/ "kMDItemKind == 'Application' && kMDItemDisplayName == '$process'")
echo "App directory is: ${appdir}"
/bin/echo "Moving application ${appdir} to ${utildir}"
/bin/mv "${appdir}" "${utildir}"

mm2270
Legendary Contributor III

@nessts][/url - Good point! killall shouldn't actually kill anything its not targeted to. I guess its just a little scary to issue a killall without first verifying its needed, but in general you're right, it should be safe to do that up front and then issue the move command.

fabian_ulmrich
Contributor
Contributor

I am very happy you guys help me out. Will test this tomorrow morning and let you guys know if it works for me. But it looks really slick to me! Thanks again...

fabian_ulmrich
Contributor
Contributor

@nessts][/url @mm2270][/url Hey guys, just to let you know...You are awesome! I mixed both ideas and it works fine so far. The only weird thing I got on my test machine is an error which is saying "This policy trigger is already being run" but it isn't. Any ideas? Did a restart and killall jamf on the machine, but that did not solve the prob. May you are interested how I embedded your ideas. Here is what I did...

#!/bin/sh
## HARDCODED VALUES ARE SET HERE
## Process to look for
process=""
## Specified Policy Trigger
trigger=""

## Variables
if [ "$4" != "" ] && [ "$process" == "" ]; then
    process=$4
fi

if [ "$5" != "" ] && [ "$trigger" == "" ]; then
    trigger=$5
fi

utildir="/Applications/Utilities/"
logfile="/private/var/log/AppMove.log"
logdate=`date "+Log: %d.%m.%Y - %H:%M:%S"`
jamf="/usr/sbin/jamf"


## Creating Log
/usr/bin/touch "/private/var/log/AppMove.log" >> "${logfile}"
/bin/echo "${logdate}" >> "${logfile}"
/bin/echo "Logfile created..." >> "${logfile}"



## Check if values are set for Script in Policy Script Details
if [ "$process" == "" ]; then
    /bin/echo "Error:  No process value is specified." >> "${logfile}"
    exit 1
fi

if [ "$trigger" == "" ]; then
    /bin/echo "Error:  No trigger value is specified." >> "${logfile}"
    exit 1
fi


## Script
appdir=$(mdfind -onlyin /Applications/ "kMDItemKind == 'Application' && kMDItemDisplayName == '$process'")
if [ -e "${appdir}" ]; then
    processrunning=$(pgrep "${process}")
    if [ "${processrunning}" != "" ]; then
        /bin/echo "$process found running" >> "${logfile}"
        /bin/echo "App directory is: ${appdir}" >> "${logfile}"

        /bin/echo "Stopping process: $process" >> "${logfile}"
        /usr/bin/killall "${process}"     

        /bin/echo "Moving application ${appdir} to ${utildir}" >> "${logfile}"
        /bin/mv "${appdir}" "${utildir}"

        sleep 5

        /bin/echo "Installing fixed version of App via JAMF policy"  >> "${logfile}"
        "${jamf}" policy -trigger "${trigger}" >> "${logfile}"

    else

        /bin/echo "No process ${process} running - continue script" >> "${logfile}"
        /bin/echo "Moving application ${appdir} to ${utildir}" >> "${logfile}"
        /bin/mv "${appdir}" "${apputil}"

        sleep 5

        /bin/echo "Installing fixed version of App via JAMF policy"  >> "${logfile}"
        "${jamf}" policy -trigger "${trigger}" >> "${logfile}"
        /bin/echo "Application moved...Done" >> "${logfile}"
    fi

else

    /bin/echo "Application does not exist" >> "${logfile}"

fi      
exit 0