Category Archives: Scripts

Terminal tricks for defeating adware

So, your browser is acting up, redirecting you to scamsites, offers for MacKeeper and Mac Cleaner and other unwanted software. You have what is technically known as ‘an adware’ infection. It’s not a virus, it’s not a ‘trojan’ and it’s not a ‘worm’, but it is a nuisance and may well be associated with any of the above. What to do?

Here’s 10 Terminal tricks you can use to help identify and remove adware items. It won’t cover every situation: adware mutates faster than a flu virus on amphetamines, but it will catch 90% of the cases currently out there. For the ones it doesn’t, see the ‘Getting Help’ section at the end of this post.

I’m going to split this up into two phases, ‘Gathering Information’ and ‘Dealing with the Results’. After explaining the first half-dozen commands individually, I’ll then give you one ‘master’ or ‘mother’ command which combines them into a single execution, but you should read through the explanations first so that you know what you’re doing and what to expect.


Gathering Info
First, most adware wants to persist on your mac across logins and restarts, and that means it has to put an executable somewhere where macOS will look on start up. One place most users should be familiar with and check first is the Login Items in System Preferences ‘Users & Groups’ pane. A lot of adware will insert itself there for good measure, but most will almost certainly be in other, trickier to find places.

This is where our first Terminal trick comes in. This Terminal trick will output the contents of the main locations where adware typically hides:

1. List the contents of your Launch* folders:


ls -alF /Lib*/Launch*/ ~/Lib*/Launch*/


That’ll output the contents of three different directories, /Library/LaunchAgents, /Library/LaunchDaemons, and ~/Library/LaunchAgents. If you’re planning on getting help by publishing the results in a public forum like Apple Support Communities, then you might want to use this version, which will scrub your username out of the results:

2. Same trick, redacting personal info:


w=`id -un`;ls -alF /Lib*/Launch*/ ~/Lib*/Launch*/ | sed "s@$w@[redacted]@g"


The output of that command will have a load of files with names like ‘com.company.filename.plist’. To give you an example here’s what mine outputs (note, none of these are adware files; unsurprisingly, my Mac is adware free!).

Slipping a shell script into the /etc/ directory is a common adware trick, so let’s also run this one, which will output any files in /etc/ that have the .sh shell script extension:

3. Find shell scripts in /etc/:


ls -alF /etc/*.sh


(this one won’t contain your user name, so we don’t need to redact anything).

A lot of adware persists by running sneaky little AppleScripts from a shell script. We can detect if any of these are at work with this little spell:

4. List osascript processes targeting your browser:


ps -axo ppid,pid,command | grep 'osascript -e global' | egrep -i "if is_Firefox_running|if is_Safari_running|if is_Chrome_running" | grep -v "grep" | grep -v ' 1 ' | awk '{ print $1, $2}'


All this command outputs is two numbers, perhaps like this:

7783 7792
7783 7825
8978 8987

We’ll discuss what to do with those in the ‘Dealing with Results’ section below.

Next, we want to see what processes are actually running in the background. This will both confirm and possibly add to information we collected earlier. To do this, we need a little trick which looks like the same command twice, but which in fact operates on two different lists of processes:

5. List loaded background processes:


w=`id -un`; r="s@$w@[redacted]@g"; launchctl list | grep -v apple | sed "$r"; sudo launchctl list | grep -v apple | sed "$r"; sudo -K


When you run this one, a list of processes will be output, and then you’ll be asked to supply an Admin password on the command line (where even the key presses won’t be visible when you type). Supply the password and a second list will be produced. We will want to examine both later.

A file name common to a widespread family of adware is rec_script.sh, and this can be hidden anywhere in the user or local Library folders, so let’s run this one, too (here we will add the redacting again in case you’re posting the results in a public forum). You’ll need to supply an admin password for this though:

6. Find a common adware executable:


w=`id -un`; sudo find /Library ~/Library -name "*rec_script.sh*" | sed "s@$w@[redacted]@g"; sudo -K


This one may take a couple of seconds to complete.

That concludes the first step of our info gathering stage, but for convenience, I’m going give you them all again concatenated into one, single ‘mother of all commands’ 😀 string. Even more conveniently, I’ve added code to output the results to a text file on your Desktop, called ‘adware_search.txt’, so after running the code below go look for ~/Desktop/adware_search.txt in Finder. If you’re posting to a public forum, it’s much easier to copy and paste the results from the text editor rather than from Terminal.

TL;DR
If you triple-click anywhere in the block of code below, you can copy and paste the whole block into Terminal and execute all of the commands given above in one fell swoop. Remember you’ll need a password.

7. The ‘Mother’ of all the above:


w=`id -un`; r="s@$w@[redacted]@g"; f="/Users/"$w"/Desktop/adware_search.txt"; ls -alF /Lib*/Launch*/ ~/Lib*/Launch*/ | sed "$r" >> "$f"; printf "\n\n/etc:\n" >> "$f";ls -alF /etc/*.sh >> "$f"; printf "\n\n# osacript processes:\n" >> "$f"; ps -axo ppid,pid,command | grep 'osascript -e global' | egrep -i "if is_Firefox_running|if is_Safari_running|if is_Chrome_running" | grep -v "grep" | grep -v ' 1 ' | awk '{ print $1, $2}' | sed "$r" >> "$f"; printf "\n\n# User launchd:\n" >> "$f"; launchctl list | grep -v apple | sed "$r" >> "$f"; printf "\n\n# Root launchd:\n" >> "$f"; sudo launchctl list | grep -v apple | sed "$r" >> "$f"; printf "\n\n# Find rec_script.sh:\n" >> "$f"; sudo find /Library ~/Library -name "*rec_script.sh*" | sed "$r" >> "$f"; sudo -K




Interlude: Playing Safe
Before we move on to dealing with the results, I want to stress that you don’t want to be deleting files that you’re not sure of. Good practice is to move files to a temporary Quarantine folder, or at least move them to but don’t empty the Trash.

Even better practice is to make sure you have an up-to-date, bootable backup disk as well as a Time Machine backup, so that you can easily recover your system if you make a mistake and delete something you shouldn’t.



Dealing with the results
Looking at the output of the first Terminal command given above (Trick 1 or 2), how can you tell which are good and which are bad? In a lot of cases, you’ll recognise the app or developer name. TunnelBear, for example. “Sure, yeah, I’ve got that” and so on. Others, however, will look and sound weird, like these (all genuine adware file names):

com.glutting_Panagia.plist
com.pPHGASlN.plist
com.phellonic.plist

Google anything you’re not sure of, and see if it’s already been identified as adware. See ‘Getting Help’ at the end of this post if you’re not sure.



Walking up & down the tree
Assuming you’ve found some candidates for removal, the next job is to find the parent and child processes associated with each. We do that with a couple more Terminal tricks.

For the first one, we want to find any process that contains the same name as our suspected adware. For each suspect, take the unique part of the name for your search term. With this one we can put all our candidates in one command like so:

8. Search for your target’s family members:


w=`id -un`; ps -axo ppid,pid,command | egrep -i "glutting_Panagia| pPHGASlN | phellonic" | grep -v ' 1 ' | grep -v grep | sed "s@$w@[redacted]@g"


Note the part after egrep -i that’s inside quote marks. Each search term is separated between a vertical bar, aka the pipe character. Note that the terms themselves are not inside quote marks individually. One pair of double-quote marks is used to encapsulate all terms.

So to use the command above replace “glutting_Panagia| pPHGASlN | phellonic” with “search term 1 | search term 2 | search term 3”, where ‘search term n’ is your search term. Of course, you can have more or less than three search terms. Just add or remove as required.

When you examine the results, so long as the first number is not ‘1’ (it shouldn’t be if you executed the command correctly, as all those should have been excluded), follow the file path shown under the ‘Command’ column using either Finder or the Terminal. If you’re sure you’ve found a baddie, send it to the Trash or your quarantine folder! If you’re not sure, see ‘Getting Help’ below.

You will need to construct and run the next command separately for each suspect. The output will give you the path to the binary being executed by the plist. In many cases, you’ll have already found that from the previous commands, but in some cases – particularly if the plist has failed for some reason or if the binary isn’t running when you do your search – it won’t. This one’s the trickiest because you’re going to have to construct most of it yourself. Here’s an example (this is actually a legitimate file, but it will serve for our purposes):

cat /Library/LaunchAgents/com.razer.rzupdater.plist | grep -iA3 program

Let’s look at how that command is structured:

9. Find more children:


cat [path to file] | grep -iA3 program


You get the ‘path to file’ part from the results of your /Library/Launch* searches, and there’s no harm in practising this one on good files to get used to the output. For each item you search, it should return something that looks like this:

Here we see the path to the executable that the plist is launching. If this were a bad guy, I’d be straight over there to send him where he belongs, too.

After working through all your suspects with Trick 8, now take a look at the results of the command to output shell script file names from /etc/ (Trick 3). If there were any results at all (hopefully there wasn’t), you’re going to have to open that file in a text editor and determine whether it is malicious or not. This is the hardest part for the novice, because there’s certainly plenty of reasons to have a shell script in /etc/ depending on what 3rd party software you’re running. I can only repeat here what I have said above: see the ‘Getting Help’ section below if in any doubt.

Next, let’s take a look at the results for the osascript processes (Trick 4). Hopefully, you got no results, but if you had two sets of numbers outputted like this:

7783 7792

then the first number is the parent process ID, and the second number is the child ID. We want to find and eliminate both the parent (again, so long as this number is not ‘1’) and the child.

Take the first number and execute this in Terminal

10. More parents on the loose:


ps [number]


Take a note of the path that’s shown and ensure it doesn’t belong to a legitimate app that you recognise. Again, if in doubt, ask Google, or see ‘Getting Help’ below.

Now, do the same with the second number, the child process. Work through however many numbers were output, ‘quarantining’ as you go.

Almost there! Take a look at the output of the two launchd lists (Trick 5). You should have a good idea by now which ones are suspect and which are OK. You may have found the paths to any suspicious ones already, but if not, we’ll use the same command as we just used with the osascript processes. Here’s the output on my machine of the Trick 5 command (all legitimate) for comparison:


We’re only interested in the first number (the second one is status code). For any suspicious process, take the first number shown in the list, and use the Trick 10 command on these to find the parent file path (you know what to do with the ones that aren’t legitimate!).

If there is only a ‘-‘ dash instead of a number, it means that process is or was loaded but is not currently running. That dash may or may not be followed by another number that is not ‘0’. That number is just an error code and isn’t really relevant to us here. For any of your suspects that have failed like that, hopefully the info you gathered earlier will give you some clues (if not, see ‘Getting Help’ next).

Finally, anything found in the ‘find’ command (Trick 6) is almost certainly malware. Of course, be mindful that it’s entirely possible a legit’ script could accidentally have a name clash and be called rec_script.sh, but it’s highly unlikely and definitely should be examined closely. Also, if you see that the path is within an application bundle like this …Contents/MacOS/rec_script.sh, don’t hesitate to pull the trigger on that one.



Getting Help
I want to repeat that doing this safely and effectively takes practice and experience, and you should in no way be surprised that, if you don’t have that experience, you’re not sure whether something you’re looking at is good or bad, or that you go through all of this and still can’t find the problem. There’s some fairly obscure ways that adware and other malware can infest and persist on your mac that only experts will be able to advise you on. Throughout this post I’ve glossed over a few situations where you’ll draw a blank, and that’s because most of the other techniques for spotting malware require that experience.

To ameliorate this, I wrote an app called DetectX to deal with this and many other things, and you can download it and use it without any requirement to pay (though registration is encouraged for regular users). You can also use it to get personal, free-of-charge, help from me through the Help > Report a Problem to Sqwarq Support if your troubles persist.

Let me be clear why I don’t charge for this personal service: the payoff for me is I get to improve my app’s heuristics from what I learn about infections that DetectX doesn’t automatically detect. All information is kept strictly confidential and I do not sell or use your email address or other information for any marketing purposes whatsoever.

If you want to read more about me, also see the about page on DetectX’s parent site, Sqwarq.com.

Happy hunting! 🙂





how to tell if your mac is too hot





The sound of the fans spinning up on your mac is never a welcome noise, but it’s usually completely normal. Determining the fan speed without 3rd party software isn’t easy, but not impossible:

do shell script "SD=~/.spindump.txt; rm $SD; spindump 1 1 -file $SD; grep 'Fan speed' $SD; rm $SD" with administrator privileges



Copy and paste the above into your (Apple)Script Editor and run it. You’ll need an Adminstrator password.





However, that doesn’t really tell you what you want to know: is my mac too hot or not? Should I do something about it?

Fortunately, we can get a better idea of the mac’s thermal state (and we don’t need admin privs to do it!), with this script:



The script not only reports the mac’s thermal state, but prints out Apple’s recommended advice, if any. Uncomment the last line of the script to get the result in a display dialog box; otherwise, you can just read the result in the results pane of your script editor.

Enjoy! 🙂


Featured Image: Flicker

how to stop ransomware infecting a backup disk

caged_egg

 

If you use a scheduled backup task such as Time Machine or Carbon Copy Cloner, any ransomware infection of your internal drive could soon propagate to your scheduled backup.

To help ameliorate that, I’ve produced a script that will abort a scheduled backup task using Carbon Copy Cloner if a user-defined percentage of changes have occurred in a designated ‘Canary’ folder.

Here’s how it works. In order to be successful, ransomware must change a large percentage, if not all, of your personal files in your Home folder by encrypting them. That means we can determine if a folder has been encrypted by looking for an unusual amount of changes or additions since the last backup.

A Canary folder is a folder that we use to warn us of precisely that. It should be a folder that contains some random dummy files (.doc, .png, .xls files etc), and/or a folder which you don’t make large changes to from one backup to the next. The script itself will change the folder slightly each time it runs, to ensure that the Canary folder does not look like it’s ‘stale’ (which might cause an attacking script to ignore it).

The key to the Canary is that the percentage of files changed or added on each scheduled backup is less than the threshold you set in the script. The default is set to no more than 10%. If the number of files changed or added is higher than that, then the backup aborts. You can of course change the default to a bit higher if you use a ‘real’ folder that you don’t change often, but remember we’re only talking changes between one scheduled backup and another, so it will also depend on how frequently your backups are scheduled.

For example, I have a 2-hour scheduled backup and I use my ‘Documents’ folder as the Canary. Since I only use that folder for long-term archives, it is actually rarely changed, and certainly never as much as 10% within 2 hours, and that makes it a perfect choice as a Canary. You can pick any real, rarely used folder or you can set up a complete dummy folder if you prefer.

If you do pick a real folder, keep in mind its size. The larger the folder, the longer it’s going to take the script to determine the differences between it and the last backup of it. A couple of thousand files is OK, but once you get into the tens of thousands you might find the script takes several minutes to complete. With only a few hundred files in my Documents folder, it takes literally a second or two.

Here’s a sample output from the log file the script produces in the ‘Canary’:

 

Destination /Volumes/Backup Disk/Users/phil/Documents has 360 files in the folder. There are 3 changes between it and the source /Users/phil/Documents. The threshold for aborting the task is 10 percent, or 30 changes. Result: task will run.

 

For our strategy to be successful, we need to ensure the attacking script doesn’t ignore the Canary and does try to encrypt the Canary before the next backup is scheduled. For that reason, if you opt for a complete dummy folder, you might like to give it a name so that it’s somewhere near the beginning (alphabetically) of your Home folder. Since the Canary folder will be slightly modified each time the script runs, it should get hit early if the attack is looking either for recently modified files or just starts trawling your home folder in ascending name order (and I know what you’re thinking: what about descending order? Sure, you could add another Canary at the end, and modify the script to check both ;)).

Note that this script is for use only with a regular, scheduled backup task, and only for use with Carbon Copy Cloner (version 4). We’ll be posting about Time Machine strategies later.

Another note of caution is that while this script should stop your scheduled CCC task from infecting a backup drive, it won’t stop an attacking script from attempting to encrypt any mounted drives it finds by itself. That really depends on the sophistication of the attack. To that end, we’ll soon be posting a general strategy for detecting a ransomware attack on your internal drive using multiple Canaries and a bit of Folder Action script magic. Stay tuned for that.

In the meantime, here’s the script. Due to the vagaries of WordPress.com formatting, I’ve hosted it over on my pastebin. Please read the extensive comments, which also explain how to set it up and how to use it. Any questions, drop a comment below. 🙂

Screen Shot 2016-04-29 at 11.00.23

 

 

Picture Credits: ‘Caged Egg’ by Marije Berting

 

 

OS X Messages character counter

Messages Counter

With OS X’s Messages app now able to send SMS, some might find it useful to have an idea of how many characters have been typed in the message field.

Here’s a bit of AppleScript and Automator magic that will do that for you. Assign it a hotkey to make it a Service, and you can quickly get a character count with the stroke of a key (alternatively, you can invoke it from the Services menu).

Download ⬇︎.

After downloading, click through to install (it’s code signed, so it should pass GateKeeper’s default settings). For the hotkey, you’ll need to set that up in System Preferences > Keyboard > Shortcuts > Services, like so:

Screen Shot 2014-10-30 at 18.08.14

When you run it for the first time, you may be asked to allow Automator and/or Messages access to System Events in Accessibility here, too:

accessibility pref pane

change the Dock position

dock position
One of Yosemite’s minor irritations is the removal of the Dock position menu item from the Apple menu.

Now we’re supposed to go hunting around on the Dock for the tiny Dock item separator and control-click it to get the menu, or open up System Preferences > Dock. All too fiddly for my taste.

The following script will rotate the Dock position through left, bottom and right. Just copy the code below and paste straight into a Script Editor document. Hit the Run button to see it in action. Then, save the script to your ~/Library/Scripts folder. Use FastScripts or set up a Service with Automator (example here) to create a hotkey.

Now you can change the Dock position with ease. 🙂

tell application "System Events"
 tell dock preferences
   set x to screen edge
   if x is left then
    set properties to {screen edge:bottom}
   else if x is bottom then
    set properties to {screen edge:right}
   else
    set properties to {screen edge: left}
   end if
  end tell
end tell

applescript: make your own battery health meter

main
A couple of weeks ago, I posted about how to extract numbers from strings. That led one reader to wonder what use they could make of such a handler. That sounded like an invitation for a little AppleScript tutorial, so in this post we’re going to build our own, colourful and highly useful battery health meter. In the process we’ll not only use the numbersInString handler I posted last time, but learn how to make our AppleScript displays a little more colourful by adding images, and we’ll take a quick look at some very useful Bash utilities that will do some of the heavy lifting for our little app. So, open up your AppleScript editor and let’s get started!

Step 1. Grab the returnNumbersInString(inputString) handler I posted here, and paste the code into a new, blank AppleScript editor window. Hit ‘cmd-K’ to turn it into ‘pretty text’ and check that it compiles OK.

Step 2. Underneath that, hit return a couple of times to create some white space, and define a new handler like this:

on powerstats()
set iconAC to ""
display dialog iconAC & "Power Source: " with icon 1
end powerstats

Hit ‘Cmd-K’ again to compile, then underneath our new powerstats handler, hit return to make some space again and type

powerstats()

Hit ‘cmd-R’ this time, which will build and run our code at the same time, and you should get the nice if not terribly useful result as so:

icon1

Believe it or not, that’s all it takes to get the core of our app, and all that remains now is to fill out the powerstats() handler and the display dialog command with the details.

Step 3: You might have been wondering what that ‘iconAC’ variable at the beginning of the display dialog command was doing, since all we did was set it to an empty string with “”. That was a placeholder. Let’s put something in it.

First, place the cursor between the two quote marks in the line that reads

set iconAC to ""

Now, either use the keyboard shortcut control+command+spacebar, or open the Character Viewer from the Keyboard menu bar (check the System Preferences > Keyboard | Keyboard: Show Keyboard & Character Viewers in menu bar item if necessary). Pick an image you like to represent AC Power. You can find the same image as I used by typing plug in the search/filter bar, but feel free to choose any image you like.

When you find the image you want, double-click it, and you should see it inserted between the quotation marks in your AppleScript. With the cursor placed immediately after the plug character but before the final quotation mark, hit the space bar three times. That’ll position it just nicely with our ‘Power Source:’ text:

icon2

OK, we’re going to set the other images we need in the same way. So, now place the cursor after the quote marks on the ‘set iconAC ‘ line, and hit return to create a space between that line and the display dialog line.

Now add the following lines, but do not include the words in orange like #battery after each set of quote marks. I’ve included those here just as search tips to help you find appropriate characters in the Character Viewer. As before, put the cursor between each set of quote marks and use the suggested orange words to find the images. Of course, you can use any image you like, but don’t forget to add the three spaces after the ASCII image.

set iconBatt to ""    #battery
set iconCharge to ""    #voltage
set iconTime to ""    #clock
set iconHealth to ""    #clover
set iconCycles to ""    #cyclone
set iconWarning to ""    #warning

Now we’re going to update our Display Dialog command so that we get the images at the beginning of a new line. We do that by adding

& return &

between each variable. Also, we don’t need all the images (iconBatt and iconAC are alternatives, and the warning sign appears elsewhere), so we’ll just add the ones we know will always be displayed. Finally, we’ll add an extra

return &

between iconTime and iconHealth to create some space. Update your Display Dialog command so that it now looks like this:

display dialog iconAC & "Power Source: " & return & iconCharge & return & iconTime & return & return & iconHealth & return & iconCycles with icon 1

When you hit ‘cmd-R’ it should now give you this:

iconsAll

Step 4: Ok, we’re done with the images, but not quite with the Display Dialog command. We need some more static text in there, so edit the command to look like the following:

display dialog iconAC & "Power Source: " & return & iconCharge & "Current Charge: " & return & iconTime & return & return & iconHealth & "Battery Health: " & return & iconCycles & "Cycles: " with icon 1

Be careful to ensure you close every quote and add an ampersand between every term and every return, or your code won’t compile correctly. Feel free to cut and paste it from above if necessary, but you should now have something like this:

add static text

This is all the ‘static text’ — text that will appear every time we run the script. As you can see, there’s some parts missing, as they will need to be added depending on the state of our battery.

Step 5: Coding time! We need to get our data for the battery before we can do much else, and for that we’re going to use a couple of unix utilities. Rather than messing around in Terminal, though, we’re going to let AppleScript manage them for us using the ‘do shell script’ command. First, we’ll ask pmset for a load of information about the machines power management settings, then we’ll ask grep to narrow it down to just the bits we’re interested in. To do all that, we’ll add the following short but powerful command to our powerstats() handler. Place the cursor on a new line after all the set icon commands, but before the Display Dialog command. Then type the following:

do shell script "pmset -g everything | grep Cycles"

Now run the script again and hit the “OK” button. The dialog will look the same as before, but this time we’re interested in what is in the ‘Replies’ (not ‘Result’) panel in the lower half of the AppleScript editor:

pmset

Note you won’t see this until after you hit the “OK” button on the dialog panel. What we need to do now is capture this result in a variable so that we can start extracting some of those useful numbers, so immediately underneath this line, add:

set x to the result

set x to the result

Step 6: In order to understand what follows, temporarily add the following two log lines:

log word 1 of x

Now run the script. Run it once with the power supply connected, then again with the machine running on battery power and compare the output in the ‘Replies’ field after you’ve hit the “OK” button.

The output of the log lines is shown in the Replies field between

(* *)

and they tell you the values of the variables. “Word 1” is the first text item in the result (exactly what delimits text items in a script depends on a built-in AppleScript variable called text item delimiters, which you can read about here).

If the AC Power is connected, word 1 should be “AC”, otherwise, it should be “No”. Similarly, word 2 should be either “charging” or “not” (sometimes the battery doesn’t charge due to a poor connection or if its more than 95% full). If AC is not connected, Word 2 should be “AC” (Word 1 and 2 together, in this case read “No AC”). However, different macs may have different power management options, so do some tests and check that you get the same results. If you don’t, you’ll need to experiment logging different words to find out which words correspond to my ‘word 1′ and word 2’. Here’s a summary again of the word numbers you need to determine for each of the values, with those on my machine given in brackets:

AC connected: word (1)? = “AC”; word (2)? = “charging” or “Not”
On battery power: word (1)? = “No”; word (2)? = “AC”

If your machine gave different results, make a note of which word number corresponds to my word 1 and word 2, and wherever I mention ‘word 1’ and ‘word 2’ in the scripting below, substitute those for the correct word numbers you found in your tests.

That these words always appear in the same position on the same machine is a very handy fact that makes it easy for us to determine whether the mac is running on battery or mains power, and in the latter case whether the battery is charging or not.

In the next step we’ll now put this information to good use in our script. First, however, remove all the log messages from the script.

Step 7: It’s time to add some more code to our powerstats() handler. Add this conditional test to your script, remembering to substitute any differences in word number you found in your logging tests:

iconWarning

This code assumes the AC is connected and sets the variable ‘charger’ to display whether the battery is charging or not. However, we need to set that variable to an empty string if the mac is running on battery power, so immediately underneath add another conditional:

pwrsource

In the Display Dialog command, replace iconAC with pwrSource as indicated in the image above. This will allow the Display to change the image accordingly. At this point, compile and test your script, both with the power supply connected and disconnected, ensuring that the icon changes accordingly.

If that’s working as expected, add the variable _t to the Display Dialog command immediately after the iconTime variable. Don’t forget to add another ampersand along with it as shown:

_t
Again, compile and test your script, both on battery and AC Power.

Step 8: Time to do some math. You may remember we started the script by adding the returnNumbersInString(inputString) method, and now it’s time to use it. We want to extract all those numbers returned by the do shell script command, and currently stored as a text string in our variable, x. We’re going to need some of them as numbers because we’re going to perform some math on them to get the battery percentage health.

Start by adding the following line, which calls the handler and gets the numbers back as a list of integers:

numbersInString
Item 1 of nums should be the battery’s current charge. Test this by adding a temporary log statement immediately after the set nums line:

log "item 1 of nums is " & item 1 of nums

Run the script, hit “OK”, and examine the Replies panel. Compare the output of the do shell script statements, and it should be clear whether you’ve got back the battery percentage or not. If not, continue logging till you hit the right item number. I’m going to assume that you got item 1 (if you didn’t, replace my mention of ‘item 1’ with whatever yours was in the following lines), so let’s remove the log statement, and replace it with this:

set percentage to item 1 of nums & "%".

Now, down in the Display Dialog command, add the variable ‘percentage’ and another ampersand in the place shown:

Screen Shot 2014-08-25 at 21.24.08
Run the script and hopefully you should now see that your battery percentage is correctly shown:

show battery percentage
Looking at the display reveals we haven’t added in the Power Source variables to the Display Dialog which we defined earlier, so do that now:

pwr & charger

Step 9: The next step is to add the time, but this is tricky on several counts. First, if you examine the number returned by do shell script in the Replies panel, you’ll note the hours and minutes are colon-separated. As far as our list is concerned, that makes them two different items, so we have to get the hours and minutes separately (items 5 & 6 on my machine; use logging to check what they are on yours).

Secondly, if the minutes are between “00” and “09”, AppleScript will just return a single-digit between 1-9, cutting of the “0”. That’ll mean we’ll end up with a weird display for say “1:05” as “1:5”. To counter that, we’ll have to test whether the minutes is less than 10 and add a “0” back in to the string if so. Also, we’ll have to add “hr”, “hrs” or “mins” depending on how much time is remaining or left to fill the charge.

As if that wasn’t enough, there’s a problem with the power manager: if you use Apple’s battery/power icon in the menu bar, you’ll notice that if you click on it straight after changing the power source, you’ll get a “Calculating Time till Full” or “Calculating Time Remaining…” message. That’s because it takes a minute or so for the power manager to update. The menu bar icon will update live, but we don’t have that luxury. Instead, we’ll add a warning later to alert users to this and ask them to run the script again after a short delay.

Woah. That’s a lot of conditions, so here goes. Add the following immediately above the Display Dialog command:

if item 5 of nums = 0 then
set hrmins to " mins"
else if item 5 of nums = 1 then
set hrmins to " hr"
else
set hrmins to " hrs"
end if
if item 5 of nums is greater than 4 then

if pwr is "AC" then
set t to "Calculating...try refresh in 2 mins"

end if

else
if item 6 of nums is less than 10 then
set theMins to item 6 of nums as string
set theMins to "0" & theMins as string
else
set theMins to item 6 of nums as integer
end if
set t to item 5 of nums & ":" & theMins & hrmins
end if

And for all that code, we only need to add one variable and an ampersand to our Display Dialog:

Step 9 v2


There is one remaining problem, which is that if you run the script immediately after changing the power source, although the message “Time to Full” or “Time Remaining” will change, the time itself may not. This is for the reason stated earlier: its inherent to the way the power manager works. We’ll do our best to help the user by adding a Refresh button later, but otherwise this is a shortcoming we’ll have to live with.

Step 10: It’s now time to get down to the real point of this script, which is to tell the user something that the battery meter in the status bar does not: the battery health and the battery cycles. The number of charge cycles the battery has been through is, naturally, given by the ‘Cycles’ figure. Battery health, however, is not data outputted natively by the power manager. Rather, it is a percentage of the Battery’s design capacity and its current ‘fully charged capacity’ or FCC. As you might expect, these two figures are represented in the do shell script output by “Design” and “FCC”, and it is largely because we need to do a mathematical operation on these that we needed the numbersInString handler.

To figure out the Battery health, we’ll divide the Design capacity by 100 to obtain 1%, then divide the FCC by this number to figure out how many percent it is of the Design capacity. That bit of math is represented by the function FCC/(design/100). In order to avoid a whole load of decimal places, we’ll also use AppleScript’s built-in round() handler to return a whole number. Finally, we’ll add the “%” sign to the string and add the ‘battHealth’ variable to the ‘Display Dialog’ command.

Here’s the code to be added, again after the last line and before the Display Dialog command (reminder: don’t forget to check using the logging technique I showed earlier that your item numbers are the same as mine, and to substitute your own for mine if they are different):

set FCC to item 3 of nums as integer
set designCap to item 4 of nums as integer
set battHealth to (FCC/(designCap/100))
set battHealth to round(battHealth)
set battHealth to battHealth & "%"

battHealth

Don’t forget to add the battHealth and ampersand to the Display Dialog, as shown above.

Step 11: Almost there. Let’s add the Cycles, which is fortunately a simple one liner:

Cycles
Does that say minus 3? Yes indeed it does! A little trick with AppleScript lists and strings is that you can count items backwards from the end using the minus sign,where -1 is the last item, -2 the item before it and so on (I thought I’d just throw that in as an extra since this command was so straightforward!). As always, check the position by using logging in your own script.

Step 12: If you run your script now you should find it’s complete. To wrap up, we want to go back to where we started, and that’s improving the look and functionality of our Display Dialog box. The first thing to do is fix the buttons. We don’t need a “Cancel” button, since the “OK” button does the job of dismissing the script, but we would like a “Refresh” button, so the user can run the script again from the dialog box. To add the the buttons, change the Display Dialog command and add a conditional statement after (not before this time) it. We’re also going to add a title for the box while we’re at it:

refresh button

final

Step 13: Your script is done, but to really finish it off, we should turn it into an app that we can run off the Dock, and to which we can add a custom icon. To create an app, choose “File > Export” and change the File Format to App. Give your script a name like “batteryPowerStat” and save it in your Applications folder.

Step 14: All you need now is an icon. You can either make your own, or you can download mine. Once you have an icns file, change its name to ‘applet.icns’ and add it to the Application bundle. To do that, control-click on your new app in the Finder, and choose ‘Show Package Contents’. Navigate to Contents > Resources, delete the file that currently exists there called ‘applet.icns’ and replace it with your custom icon.

You may need to log out and log in again before OS X flushes the old file from its memory and displays your new one.

Step 15: Only kidding! There is no step 15. 😀 I just wanted to stay “Congratulations”. If you made it this far, I hope you picked up a few AppleScript tricks along the way to creating your own battery health meter. If you need the complete code, you can find it on my Pastebin site here.

Enjoy! 🙂

run Terminal commands from any app

In this post I’m going to show you how you can select a piece of text in any app and have it run in Terminal simply by hitting a hotkey. The trick is especially useful for running commands you find on websites (like this one!) in a browser like Safari or Firefox.

This 20-second clip demonstrates running a command from a Firefox browser and another one from TextEdit, but you can also do it from an AppleScript editor window (and indeed any app that has selectable text), which can be useful for testing the formatting of your ‘do shell script’ commands and the like:






The first thing you’re going to need is to create an Automator workflow, add an AppleScript action and insert some code. Really? Nah, just kidding. I did it for you. 🙂 Just download, unzip and double-click the .workflow file to install the completed Service:

Download Run in Terminal.workflow.zip

Click through the various dialog boxes and choose ‘Install’ on the last one* (note for Snow Leopard users: the service will open directly in Automator; just do ‘command-shift-S’ to name it and save it).

Screen Shot 2014-05-09 at 12.10.58

All you need to do now is set the hotkey. Open  > System Preferences.. > Keyboard | Shortcuts and click ‘Services’ in the sidebar. Scroll down the window till you see the ‘Run in Terminal’ command. Click on the far right to add a shortcut of your choice. The one I used in the video is ‘command-option-control-T’ (‘T’ for ‘Terminal’ helps me remember the shortcut).

To use the Service, just highlight any Terminal command by triple clicking it and pressing your hotkey. Try this one,

cd ~/Desktop; ls -alF

which lists all the visible and invisible files on your Desktop, as a test.

You can also get to the Service from both the contextual menu (right-click > Services) and the application menu bar at the top (e.g., Safari > Services).

As a bonus, try out your new Service on the Terminal command in this post, and now you’ll be able to run Terminal commands even from Quick Look previews in Finder!

Enjoy! 🙂


Carbon Copy Cloner: see last back up date

CCC Last Backup Service

If you’re a user of Bombich Software’s excellent Carbon Copy Cloner but you’re not doing backups as scheduled tasks, you may wish there was a way to find out the last time you successfully completed a backup task.

Unfortunately, CCC doesn’t provide an easy way for users to see this information natively, but in this post we’re going to add it through a bit of AppleScript and Automator magic.

As it turns out, CCC does keep a log of all your past backup details stashed away in a CCC.log file buried in your local domain’s Library folder. You can view this file in Console, but it’s a bit of a pain. Wouldn’t it be nicer if you could just hit a hotkey like ‘Command-Control-C’, say (you know, for ‘CCC’ 🙂 ), and get a dialog box like this:

CCC Last Backup date
If you think so too, then download my Automator workflow:

For Lion, Mountain Lion and Mavericks:
Download for 10.7.5 thru 10.9.2 📀

For Snow Leopard:
Download for 10.6.8 💿

Double-click on the .zip file and double click again on the unzipped workflow file. You’ll get a warning message saying that you’ve downloaded the file from the internet (from me, actually!). After clicking ‘Open’ to dismiss the warning, for all users except 10.6, click ‘Install’ on the the following dialog box:

Install workflow

After clicking ‘Install’, click ‘Done’ to dismiss the confirmation dialog box that pops up.

For those of you running Snow Leopard (10.6.8), after clicking ‘Open’ the workflow should open in Automator. Hit ‘command-S’ to save it as a Service.

For all users, if you now click up to any application name next to the  Apple near the top left of your screen (see the screenshot at the top of this post) and scroll down to ‘Services’ you should see the new Service already there. If you don’t, try logging out and logging back in to your user account.

Once you can see the workflow in the Services menu, go ahead and give it a click to test it out. 🙂

A couple of notes on usage:

Carbon Copy Cloner does not have to be open for the Service to work.

The date format display is YYYY-MM-DD.

If you want to add a shortcut key as suggested earlier, open up System Preferences > Keyboard and click the ‘Shortcuts’ tab. Down the sidebar you should see ‘Services’. Click on that and scroll way down to the bottom till you see the name of the Service. Click ‘Add Shortcut’ and hit the keys you want to use. I like ‘command-control-C’ as it’s an easy mnemonic for ‘Carbon-Copy-Cloner’.

how to clear Safari’s cookies on quit

If ever there was a free app that deserved more recognition, it’s Safari Cleaner (direct download). Developed out of a simple applescript, this app does what many people would expect Safari to have an option to do in the Preferences panels: automatically clear stored information when Safari quits.

Personally, I’ve found this particularly needsome since signing into any Google service seems to be particularly irritating. Gmail, for example, needs several clicks just to be told that you don’t want to be remembered. Safari Cleaner takes care of automatically ‘forgetting’ as much or as little info as you want without you having to remember to clear cookies or caches. It’ll also, thankfully, forget Top Sites. 🙂

Safari Cleaner

Personally, I leave my history as that’s something I regularly need across sessions, but the rest, I’m happy to be forgotten. If you’re wondering why anyone might care, well, there’s a whole bunch of reasons including protecting you from malware and malicious websites, but at least one other is nicely detailed in this Ars Technica article, which explains how cookies can be used to track your physical whereabouts.

One caveat to note with Safari Cleaner: in my tests, I’ve noticed that if you click and restart Safari in rapid succession (within about 5 seconds or less), the script hasn’t had time to complete running and caches and cookies aren’t cleared. To be safe, you probably want a nice 10 secs or so between quitting and relaunching Safari if you absolutely must be sure the previous session was wiped out.

Once you’ve run and set up Safari Cleaner’s options, you can quit the app and it’ll just carry on working in the background. Launch the app only if you want to change your options. If you want to uninstall it, note that there’s an uninstaller in the DMG, so don’t throw that away.

Get Safari Cleaner (direct download)

 

how to correct the external monitor resolution

apple_display
A problem that’s been bugging me since at least Mountain Lion is that sometimes when I connect my external monitor to my Macbook Pro, the display resolution is incorrect. The problem is pretty annoying as it often occurs on wake if the MBP goes to sleep even when the external monitor hasn’t been disconnected.

There are a number of solutions to this problem, and I’ve used them all. Some are less irritating than others, but in this post I’ll give you a run down of the options.

1. The old fridge magnet trick
As I often use a tiny magnet to put my MBP display to sleep while keeping the lid open, normally putting the magnet on and then taking it off again will cause the displays to reset. But this method is annoying both because I’m often connecting to external monitors away from home and because I often misplace that tiny magnet! The other problem with this method is it doesn’t always work… 😦

2. Put the external monitor to sleep with a Hot Corner
Go into System Preferences > Mission Control, and set one of the Hot Corners to ‘Put Display to Sleep’ (not ‘Start Screen Saver’). When your mac wakes up and the monitor is in the wrong resolution, move the cursor to the Hot Corner, wait a couple of seconds, and move the cursor back to the centre of the screen.

3. Activate ‘Detect Displays’
Ok, two ways to do this. The manual way is that you open System Preferences, hold down the ‘option’ key and hit the ‘Detect Displays’ button at the bottom of the window. Note that you won’t see this button unless you’re holding down the ‘option’ key. After the display resets properly, quit System Preferences. My main beef with this method is it’s totally disruptive to my workflow, so much in fact that it makes me angry every time I use it!

Fortunately, you can lower the inconvenience with the second way, which is an AppleScript that does the same thing automagically.

Update Jan 2015:
Partly in response to this problem, I’ve written an app called DisplayDroid which detects when a monitor is connected or disconnected and automatically runs a script in response. The script below is built into DisplayDroid as one of the presets that you can choose!
Find out more about DisplayDroid…

try
tell application "System Preferences" to quit
end try

delay 1
tell application "System Preferences"
activate
reveal pane "com.apple.preference.displays"
end tell


tell application "System Events"
tell process "System Preferences"
set frontmost to true
try
key down option
delay 0.2
click button "Detect Displays" of window 1
delay 0.2
key up option
on error
key up option
end try
end tell
end tell


tell application "System Preferences" to quit

You might want to save this in your scripts menu or make it into a Dock-able app for convenience. Don’t forget you’ll need to allow the AppleScript editor permission to use Assistive Devices.

4. A free screen utility
Unhappy with a GUI scripting solution, I started researching how to change the displays in Cocoa or from the BASH command line so that I could avoid the overhead of System Preferences popping open and closed, which is an ugly solution at best. I didn’t get far in my research before I found that someone else had already beaten me to the punch, and had even offered the code up for free. Y’gotta love the heroes of the programming community! Download the free RDM.app, which lets you change the screen resolution on any of your monitors from the status bar on your desktop. Move it from your Downloads folder into your /Applications folder. I’ve even got it in my login items for maximum convenience!

RDM

Although the app is probably slightly slower than the Hot Corner solution when I’m at home, I like it because I regularly connect my mac to all sorts of other monitors and projectors and the mac doesn’t always choose the best display. The RDM.app lets you slide through the available options much more efficiently than the System Preferences panel, too. Big respect to Paul Griffin at http://www.phoenix-dev.com for this!

5. Trash old prefs
No matter how well or otherwise any of these techniques work, the question remains: why is the resolution setting being forgotten in the first place? I haven’t nailed this down as a cert yet, but ever since I did this to solve a different problem, my monitor’s been behaving itself, too.

1. Go to

Hard Disk/Library/Preferences/System Configuration

Now make sure you’re at the right place because there’s another ‘System Configuration’ folder at /Library/System Configuration, and you definitely don’t want to be messing with that one. Also, this is the Library folder at the root of your hard disk and NOT your user account library (i.e, the path is /Library, not ~/Library). Check that path. Here it is again

Hard Disk/Library/Preferences/System Configuration

2. OK, click on that folder, and copy it over to your Desktop. Now go back and delete it from /Library/Preferences (or hold down ‘option’ while you drag to do a ‘move’. I prefer the first way; it’s safer, if slower).

3. Restart and test.

Hopefully, if you’ve been venting at the ears like me over the external display problem, one or more of these options will help lower the frustration!

🙂

Related Posts:
DisplayDroid from Applehelpwriter



Featured Picture: apple_display by 3DEricDesign

%d bloggers like this: