Shirt Pocket Discussions  
    Home netTunes launchTunes SuperDuper! Buy Now Support Discussions About Shirt Pocket    

Go Back   Shirt Pocket Discussions > SuperDuper! > General

 
 
Thread Tools Rate Thread Display Modes
Prev Previous Post   Next Post Next
  #3  
Old 01-22-2006, 11:50 AM
Syzygies Syzygies is offline
Registered User
 
Join Date: Jan 2006
Posts: 23
Revised code

Here is a revised version of my code to selectively mount and unmount volumes, and call SD! scripts unattended. I've sorted out various issues, and it now works fine as a cron job; I rely on it nightly.

Overall, the code has been improved by never telling anything to the Finder. 'unmount' now only unmounts the given volume, without ejecting other volumes on the same disk. It is possible to have an AppleScript such as this that calls 'diskutil' crash on rare occasions. I don't know why, and I'm not sure that I'm actually doing anything wrong. (SD! itself sometimes uses 'disktool' instead of 'diskutil', despite Apple's efforts to wean us from it; perhaps Dave can explain why?)

Also on rare occasions, I'd run a prior version of this script unattended, and one of the volumes failed to unmount. I considered what I would have done manually had I been there, and wrote a wrapper 'unmountVol' to do exactly that. It looks like massive overkill in the calm light of day, but its precautions are entirely harmless for unattended operations.

I leave diagnostic journaling on at all times, as SD! does. If anything odd happens, this is invaluable. Note that all shell script commands are logged, together with any errors returned, even for commands that always return an error. (We wouldn't want to miss it, if one of them returned a different error.)

All forums have a high percentage of lurkers. I google and lurk various places to pick up code fragments to try, and I consider this to be the primary value of posting code on the web; I don't like to use unsupported code that I haven't rewritten myself. To be conservative, if no one else has posted here that this code worked for them, proceed with caution in modifying it for your needs.

This is an AppleScript library file, Backups Library.scpt. Opening it opens the script in the Script Editor:

Code:
property logfile : "/Volumes/User/Users/ad/Scripts/logs/log"

-- initialized, journal, shell, wait : utility routines

property new : true

on initialize()
  if new then
    set logfile to logfile & (do shell script "date '+ %Y-%m-%d.txt'")
    set new to false
  end if
end initialize

on journal(message)
  local wasnew, s, f
  set wasnew to new
  if new then initialize()
  set s to (quoted form of message)
  set f to ">>" & (quoted form of logfile) & "; "
  if wasnew then
    do shell script "echo " & f & "echo " & s & f & "echo " & f
  else
    do shell script "echo `date '+%H:%M:%S'` ' ' " & s & f
  end if
end journal

on shell(command)
  -- use full paths for any commands not in path "/usr/bin:/bin"
  local e, n
  journal("      % " & command)
  try
    do shell script command
  on error e number n
    journal("      ! " & (n as string) & " " & e)
    error e number n
  end try
end shell

on wait(interval)
  shell("sleep " & interval as string)
end wait

-- ismounted, mount, unmount : mounting and unmounting volumes

on ismounted(volname)
  try
    -- if not found, egrep exits with a non-zero status
    shell("/sbin/mount | egrep 'on /Volumes/" & volname & " \\(.+\\)$'")
  on error
    journal(" - " & volname)
    return false
  end try
  journal(" + " & volname)
  return true
end ismounted

on mount(volname)
  local a
  journal("mount: " & volname)
  if not ismounted(volname) then
    try
      -- if not found, grep and egrep exit with a non-zero status
      set a to shell("/usr/sbin/diskutil list | egrep '^ +[[:digit:]]+: +[[:graph:]]+ +" & volname & " +[.[:digit:]]+ GB +disk[[:alnum:]]+$'")
      set a to shell("echo '" & a & "' | sed 's/" & volname & "//' | awk '{print $5}'")
      shell("/usr/sbin/diskutil mount " & a & " | grep '^Volume " & a & " mounted$'")
    on error
      return false
    end try
  end if
  return true
end mount

on unmount(volname)
  local n
  journal("unmount: " & volname)
  if ismounted(volname) then
    try
      -- unmount always generates error "Volume failed to unmount", even when successful
      shell("/usr/sbin/diskutil unmount '/Volumes/" & volname & "'")
    end try
  end if
end unmount

-- mountVol, unmountVol : patient, stubborn wrappers for mount, unmount

on mountVol(pause, tries, volname)
  local n
  journal("mountVol " & volname)
  repeat with n from 1 to tries
    wait(pause)
    if mount(volname) then
      repeat with n from 2 to 8
        wait(n)
        if ismounted(volname) then return true
      end repeat
    end if
  end repeat
  return false
end mountVol

on unmountVol(pause, tries, volname)
  local n
  journal("unmountVol " & volname)
  repeat with n from 1 to tries
    wait(pause)
    unmount(volname)
    repeat with n from 2 to 8
      wait(n)
      if not ismounted(volname) then return true
    end repeat
  end repeat
  return false
end unmountVol

-- mountVolumes, unmountVolumes : apply mountVol, unmountVol to lists

on mountVolumes(pause, tries, volnames)
  local status
  journal("mountVolumes")
  set status to true
  repeat with volname in volnames
    if not mountVol(pause, tries, volname) then set status to false
  end repeat
  return status
end mountVolumes

on unmountVolumes(pause, tries, volnames)
  local status
  journal("unmountVolumes")
  set status to true
  repeat with volname in volnames
    if not unmountVol(pause, tries, volname) then set status to false
  end repeat
  return status
end unmountVolumes

-- SuperDuper!

on SuperDuperJob(volname, scriptalias)
  local wasmounted
  journal(scriptalias as string)
  journal("")
  set wasmounted to ismounted(volname)
  if wasmounted or mountVol(30, 4, volname) then
    journal("SuperDuperJob: " & scriptalias as string)
    try
      run script scriptalias
    on error e number n
      journal("script error: " & (n as string) & " " & e)
    end try
    if not wasmounted then unmountVol(30, 4, volname)
  end if
  journal("")
end SuperDuperJob

-- top level routines

on mountBackups()
  mountVolumes(0, 1, {
    "aOSX", "aOS9", "aOSX 10.4.4 min", "aOSX 10.3.9 min", "aUser", 
    "bOSX", "bOS9", "bOSX 10.4.4 min", "bOSX 10.3.9 min", "bUser", 
    "FireWire A OSX", "FireWire A"})
end mountBackups

on unmountBackups()
  unmountVolumes(0, 1, {
    "aOSX", "aOS9", "aOSX 10.4.4 min", "aOSX 10.3.9 min", "aUser", 
    "bOSX", "bOS9", "bOSX 10.4.4 min", "bOSX 10.3.9 min", "bUser", 
    "FireWire A OSX", "FireWire A"})
end unmountBackups

on runBackups()
  journal("runBackups")
  
  SuperDuperJob("aOS9", 
    alias "User:Users:ad:Scripts:Smart Update aOS9 from OS9.sdsp:Copy Job.app:")
  SuperDuperJob("aOSX 10.3.9 min", 
    alias "User:Users:ad:Scripts:Smart Update aOSX 10.3.9 min from OSX 10.3.9 min.sdsp:Copy Job.app:")
  SuperDuperJob("aOSX 10.4.4 min", 
    alias "User:Users:ad:Scripts:Smart Update aOSX 10.4.4 min from OSX 10.4.4 min.sdsp:Copy Job.app:")
  SuperDuperJob("aUser", 
    alias "User:Users:ad:Scripts:Smart Update aUser from User.sdsp:Copy Job.app:")
  SuperDuperJob("aOSX", 
    alias "User:Users:ad:Scripts:Smart Update aOSX from OSX.sdsp:Copy Job.app:")
  
  SuperDuperJob("aBack", 
    alias "User:Users:ad:Scripts:Smart Update Sources image from User.sdsp:Copy Job.app:")
  SuperDuperJob("aBack", 
    alias "User:Users:ad:Scripts:Smart Update Users image from User.sdsp:Copy Job.app:")
end runBackups
This is a typical AppleScript application file that makes a call from the above library, Run Backups.app. Once set up, it seldom needs further editing. Opening it runs the script:

Code:
set BackupsLib to (load script file "User:Users:ad:Scripts:Backups Library.scpt")

tell BackupsLib
  runBackups()
end tell
This is a typical journal entry, from the file log 2006-01-22.txt:

Code:
unmountVol aBack

07:11:37         % sleep 0
07:11:37   unmount: aBack
07:11:37         % /sbin/mount | egrep 'on /Volumes/aBack \(.+\)$'
07:11:37    + aBack
07:11:37         % /usr/sbin/diskutil unmount '/Volumes/aBack'
07:12:04         ! 1 Volume failed to unmount
07:12:05         % sleep 2
07:12:07         % /sbin/mount | egrep 'on /Volumes/aBack \(.+\)$'
07:12:07         ! 1 The command exited with a non-zero status.
07:12:07    - aBack
Reply With Quote
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Problems automating backups with applescript and crontab kbradnam General 4 01-20-2006 08:40 AM
Strongspace SuperDuper backup strategy options? parakeet General 1 12-21-2005 10:16 PM
Backup and archive strategy and method? xoshooter General 3 10-07-2005 05:28 PM
applescript help snoopy67 General 1 09-17-2005 10:07 AM
AppleScript bug? fixed! pzingg General 1 11-02-2004 07:37 PM


All times are GMT -4. The time now is 11:30 AM.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2022, vBulletin Solutions, Inc.