PDA

View Full Version : Automatic Logout


stephenfleming
01-21-2002, 10:37 PM
I'm trying to craft a Unix command line that I can add to crontab to execute a graceful Log Out of the Macintosh environment. Basically, I want to be able to walk away from my machine at night (running a backup or something), but be sure that everything gets tidied up and is ready for me to login the next morning.

This should be incredibly simple. I can't figure out how to do it either in AppleScript or from the command line. Any suggestions? Thanks!

Stephen Fleming

ginoledesma
01-22-2002, 01:17 AM
Off the top of my head I'd use kill, but that isn't necessarily gracious. If the application gets a SIGTERM or SIGQUIT, it should try to quit gracefully.

With regards to an AppleScript doing a QUIT, the issue I can think of is applications that ask for a "confirmation" when quitting, such as browsers asking for a confirmation while downloads are in progress, or documents that need saving. The Finder logout eventually times out when no response is given.

Tuxford
12-18-2007, 01:07 PM
Has this issue been solved in recent OSX releases? Set my server to login as public user. I manually login as an admin user. Want to ensure that when I walk away, the admin user will eventually automatically logout.

anika123
12-19-2007, 10:08 AM
I am no expert but you should be able to write in your scripts to modify a certain file, say a text file or something. Then set up launchd to monitor this file for changes. When it detects a change it will call the applescipt you have written that uses "system events" to logout or shutdown or whatever you want. So long as it is in the system events dictionary.
This could all be done (the backup and stuff) from a single applescript.

cwtnospam
12-19-2007, 10:38 AM
If you're going to walk away, and you want it to log out, why not schedule it to shutdown in the Energy Saver preference pane?

If you want to walk away leaving the computer running but require a password to get back in, then set your screen saver to require one. While you're at it, make your screen saver something useful like folding@home. (http://folding.stanford.edu/)

anika123
12-19-2007, 10:49 AM
If you're going to walk away, and you want it to log out, why not schedule it to shutdown in the Energy Saver preference pane?

This would work just fine but I think what stephenfleming wants to do is run a backup script that may not be done when the scheduler decides to shutdown. Or, he wants to save the most amount of energy possible and wants his computer to shutdown promptly after the backup.

cwtnospam
12-19-2007, 11:06 AM
Well, if he wants it to shutdown, the Terminal command is:

shutdown -h now

Simply logging out is another story, in which case I think it would be much more productive to use a distributed computing screen saver and set it to require a password. ;)

anika123
12-19-2007, 12:15 PM
shutdown -h now

That actually seemed to work but when I restarted; the session from the previous shutdown seemed to be active. Also, Camino acted like it had been force quit. Are you sure this works for a clean osx shutdown?

cwtnospam
12-19-2007, 12:41 PM
The man page is dated December 11, 1998 so developers should be aware of it. I did see the same problem with Camino though.

Of course, if you're going to put this in a script, it would be best to close all applications before using the command.

Oh, just in case some one has a legitimate need to logout instead of shutdown — although I can't think of one — the command key for logout is command-shift-Q. If you want it to take affect immediately, it's command-option-shift-Q. That should be easy enough to GUI script in Applescript.

Hal Itosis
12-19-2007, 02:34 PM
I don't remember the syntax offhand, but in AppleScript there is something like:

shutdown without saving

[I forget exactly... but it is slightly more "graceful".]

-HI-

anika123
12-19-2007, 03:45 PM
Wow, was this thread really started in 2002? I doubt stephenfleming even cares anymore. But the info is still good for newcomers and interested parties.

Tuxford
12-19-2007, 03:48 PM
Since the machine is server, I want it always running. Since it runs some server applications, I have it login automatically as a standard user.

To get to my private shared folders, I login as a second user sometimes, and then walk away. I want this second user to automatically logout after a period of time. Can someone consolidate these ideas into a strategy for me? Thanks.

cwtnospam
12-19-2007, 04:15 PM
You could save this as a stay open application and put it in your startup items. After about 10 seconds of inactivity, the 2:00 minute warning for logout will popup. You can cancel the logout if you're there, and it will popup after the next inactive period.

on idle
delay 10
tell application "System Events"
key down shift
key down command
keystroke "q"
key up shift
key up command
end tell
end idle

anika123
12-19-2007, 04:42 PM
I think what you want is a logout script. This is way beyond my means but this might be a relevant link http://managingosx.wordpress.com/2006/05/10/launchd-gotcha/. Anyway a logout hook is apparently what you need. I would hope that applescript could do this. Where is tw when you need him. Anyone one else with logout hook experience?

The solution by cwtnospam looks like a good solution as well.

Tuxford
12-19-2007, 06:20 PM
Great. Got the script working. Would be nice if I could also then automatically log back into the other standard user. This script just gets me to the login name screen. The other user is typically running in the background anyway. I wonder if it's energy saver settings would kick in and dim the screen at this login window?

cwtnospam
12-19-2007, 06:43 PM
Ok, then based on the code from post #9 in this thread, (http://forums.macosxhints.com/showthread.php?t=45055) let's do this:

on idle
delay 10
display dialog "About to switch users..." giving up after 10
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
delay 2
tell application "System Events"
keystroke "their password here"
delay 1
keystroke return
end tell
end idle

You need to enter the correct userID number. If your standard account ID isn't 502, change it to the correct one!

Edit: Note that providing the password in the script isn't secure. Since it's a standard account and you auto login anyway, it shouldn't be a huge problem. ;)

Tuxford
12-19-2007, 07:04 PM
This script gets stuck after the password entry, on Return. Ends up looping back at the About to switch warning. Need to click the login button. Also wonder if need to disable this script when user is in the background after switching.

cwtnospam
12-19-2007, 07:13 PM
Two things that could cause that problem:
1) The user id isn't correct.
2) The password isn't correct.

I don't think the script needs to be disabled when in the background. When I tried it everything seemed ok.

Tuxford
12-19-2007, 07:32 PM
After the script runs and gets stuck in the loop, I simply click the login button, and it switches user. So the user id and password are correct.

Seems to switch to the Finder (or maybe to the looped script) before the Return is recognized.

cwtnospam
12-19-2007, 07:35 PM
Ok, I was able to duplicate the problem. I think this should take care of it:

on idle
delay 10
tell application "Finder"
activate
display dialog "About to switch users..." giving up after 10
end tell
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
delay 3
tell application "System Events"
keystroke "password"
delay 1
keystroke return
keystroke return
end tell
end idle

ThreeDee
12-19-2007, 07:38 PM
Doesn't Leopard have new "Time Limits" in the parental controls? I don't have Leopard, but perhaps that will be of some help?

cwtnospam
12-19-2007, 07:43 PM
He's trying to logout of an admin account, and into a standard account. I don't have Leopard, so I could be wrong, but I don't thing parental controls will help with that.

Tuxford
12-19-2007, 07:48 PM
That second Return did the trick, but shouldn't ENTER be used more appropriately? Can't figure out how to keystroke ENTER?

Also, script continues to run while user is in the background, attempting to switch users? Well maybe not. But when I switch back to the user, the script is hung in the background, and unresponsive to an idle condition. How can we disable the script while the user is in the background? And make sure it is active again when switched back?

I know I am asking alot.

cwtnospam
12-19-2007, 08:15 PM
It really wasn't my script to begin with. I'm going to have to think about a better way. Probably a shell script run by launchd.

cwtnospam
12-19-2007, 10:15 PM
Ok, this seems to work:

Use Lingon to set this bash script to run every x number of minutes:
#! /bin/bash
osascript /path/to/the/Applescript.scpt


It will call this Applescript:

on run
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
end run
Your warning will be the login screen — click cancel to abort — so you might want to set the first delay to higher than 5, and the second delay could be less than 4 if you like.

Unfortunately, I couldn't find a way to check for idleness, so this will have to popup every time the bash script gets called.

Tuxford
12-20-2007, 03:18 PM
Sorry. I can barely use Lingon. Can you give an example of the pathname for an applescript named “Logoff.scpt” placed in the Applications folder? Should it be setup using the Assistant or manually?

cwtnospam
12-20-2007, 03:49 PM
/Applications/Logoff.scpt

Assistant, if that's easier for you. It doesn't really matter though.

anika123
12-20-2007, 04:07 PM
Should it be setup using the Assistant or manually?

I have no idea of what you mean by that.
Here is how to use lingon.

Say you name the first script "trigger" and the second script "logoff.scpt"
Put the first one somewhere in your path and the second one in ~/library/scripts.
Save the applescript as an app (saving as an app may not be needed) and make sure "trigger" is executable. Of course, you need to change the path in the trigger script to match the applescript location. Say, ~/library/scripts/logoff.scpt


Open lingon and on line (1) make a name as suggested.
On line (2) put the path to the "trigger" script. ~/applications/trigger.sh
Line (3) contains the time interval you want the script to wait till it starts logoff.scpt

cwtnospam
12-20-2007, 04:15 PM
I have no idea of what you mean by that.
There's a button labeled 'Assistant' that takes you through a short script to set up your task.

Tuxford
12-20-2007, 06:24 PM
Ok, this seems to work:

Use Lingon to set this bash script to run every x number of minutes:
#! /bin/bash
osascript /path/to/the/Applescript.scpt




This script will not compile. What is wrong with the first characters?

anika123
12-20-2007, 06:26 PM
Are we talking about lingon here, cuz mine has no such "assistant" button.

anika123
12-20-2007, 06:29 PM
you don't need to compile the bash script. All bash scripts start with "#! /bin/bash" just save it to somewhere in your path and make it executable.

Tuxford
12-20-2007, 06:48 PM
What is a bash script? Can't I just make a compiled script?

Lingon has an Assistant button between NEW and EDIT buttons.

cwtnospam
12-20-2007, 07:07 PM
What is a bash script? Can't I just make a compiled script?

Lingon has an Assistant button between NEW and EDIT buttons.
Just copy the script:

#! /bin/bash
osascript /path/to/the/Applescript.scpt

into a blank TextEdit document and save it as plain text. Then type this into a Terminal window:
sudo chmod +x /path/to/Textfile

Tuxford
12-20-2007, 07:50 PM
Sorry. No help. Stuck. pathname error.

cwtnospam
12-20-2007, 08:04 PM
Oops! Sorry, the path should be the path to the Applescript file, so if you put it in Applications and called it Logoff.scpt, then it should be:

#! /bin/bash
osascript /Applications/Logoff.scpt

Tuxford
12-20-2007, 08:12 PM
GM-G5-2-3:~ Me$ sudo chmod +x /Triggered
chmod: /Triggered: No such file or directory

That didn't work. The file name is Triggered, at the root level.

anika123
12-20-2007, 08:59 PM
type "ls -l /" (without the quotes) at the command prompt and paste the results here.

cwtnospam
12-20-2007, 09:40 PM
Oops, again! If you saved it as a text file from TextEdit, it puts the extension ".txt" on the file, so you'll want to get info it and change the extension to .sh and then do this in the Terminal:

sudo chmod +x /Triggered.sh

Are you sure that you saved it in the root directory though? If it's on your desktop, the path would be: /users/Me/desktop/Triggered.sh

Tuxford
12-21-2007, 02:05 PM
Done. Got a warning in Terminal, entered password. Now what?

Should Logoff be saved as a 'stay open app' or a scpt?

Should Trigger be saved as a 'stay open app' or a scpt?

Using the assistant in Lingon, what is the Command line needed to run Trigger periodically?

anika123
12-21-2007, 02:36 PM
Since trigger is not an applescript just follow the instructions in #34 except when you save the file save as trigger.sh

logoff is an applescript and can be saved as logoff.scrp and it should work

If you get the latest lingon you dont have to enter a command line for it to work and there is no assistant button. Opps, I just noticed you need 10.5 for the latest lingon. I will try to get a command line for you.

Meanwhile you should try running the command by hand to make sure everything works. After saving everything properly you should be able to open terminal and type "./trigger.sh" (without quoets) and have it work.

cwtnospam
12-21-2007, 04:35 PM
Use Lingon to set this bash script to run every x number of minutes:
#! /bin/bash
osascript /path/to/the/Applescript.scpt


It will call this Applescript:

on run
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
end run
Your warning will be the login screen — click cancel to abort — so you might want to set the first delay to higher than 5, and the second delay could be less than 4 if you like.

Unfortunately, I couldn't find a way to check for idleness, so this will have to popup every time the bash script gets called.
Done. Got a warning in Terminal, entered password. Now what?

Should Logoff be saved as a 'stay open app' or a scpt?

Should Trigger be saved as a 'stay open app' or a scpt?

Using the assistant in Lingon, what is the Command line needed to run Trigger periodically?
The way I was doing it, you'd have two files. One is a Bash script and the other is an Applescript. I think that since the Bash script is only one line that calls the Applescript, you could get Lingon to do the Bash portion for you by using a line like this:

osascript /path/to/the/Applescript.scpt

Tuxford
01-11-2008, 06:53 PM
Been out for the holidays. Got the scripts to work, but need the second script to trigger on 'idle' rather than on 'run'. A simple substitution of the loop command doesn't seen to work right. I am missing something.

So I need the bash script to periodically ensure that the logoff script is running. I need the logoff script to wait until an idle period is up, before logging off.

This should be easy, but I need a clue. Thanks.

cwtnospam
01-11-2008, 07:16 PM
How did you do it then? The way I've suggested is that launchd (set up with Lingon) would periodically call a bash script:
#! /bin/bash
osascript /path/to/the/Applescript.scpt

The bash script runs the Applescript:
on run
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
end run

So there's no need to have an idle handler.

I don't know why it didn't hit me earlier, but you could do the same thing this way:
launchd periodically calls bash script:
#! /bin/bash
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
osascript /path/to/the/Applescript.scpt

which calls this applescript:
on run
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
end run

Tuxford
01-11-2008, 07:48 PM
I used lingon as suggested to 'periodically' run the Logoff script. But the logoff script then runs immediately, and after the short delay, logs off. It is contained within an 'On Run' loop.

I don't want the Logoff script to run if I am an active user. I want it to wait until an idle condition of some 20 minutes before logging off. If I am an active user for an hour or two, I would prefer it did not interrupt my work.

hayne
01-11-2008, 08:24 PM
I don't want the Logoff script to run if I am an active user. I want it to wait until an idle condition of some 20 minutes before logging off. If I am an active user for an hour or two, I would prefer it did not interrupt my work.
Google for:
HIDIdleTime
and you should find discussion of using this (e.g. in the output from 'ioreg -c IOHIDSystem') to find out how long the system has been idle.

cwtnospam
01-11-2008, 08:56 PM
Ok, here are the two scripts.

Shell script, to be called by launchd:
#! /bin/bash
idl=$((`ioreg -c IOHIDSystem | sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))
if [ $idl > 30 ]
then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
osascript /path/to/applescript.scpt
fi

Change the text in red to suit your needs. If you use Lingon to set launchd to call the shell script every couple of minutes, an idle time of 30 seconds should be fine.

Applescript, called by the shell script:
on run
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
end run

mark hunte
01-11-2008, 10:11 PM
Hi cwtnospam,
Just a thought, But how about merging the two scripts together into one shell script. Which get called by launchd.



I did not test the script below in lingon, but did test this in terminal and used a:
"sleep 40"
as the first line.

I also changed your HIDIdleTime line to one I use for this sort of thing.
I could not get you line to work, even on its own in terminal.
Also noted you will not get a correct results if you use the () brackets around the HIDIdleTime line. as the result will return with brackets (40)
If you use the greater than symbol ">" and the brackets, it will not be picked up that what you are getting is not an integer expression.
I only got clued up on this when I change the symbol to -gt and got the error:
integer expression expected.
Anyway hope this helps.


#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
EOT
fi

cwtnospam
01-11-2008, 11:16 PM
Hi cwtnospam,
Just a thought, But how about merging the two scripts together into one shell script. Which get called by launchd.
I was thinking of that, but at the time I was just happy I'd gotten it to work. ;)
I did not test the script below in lingon, but did test this in terminal and used a:
"sleep 40"
as the first line.

I also changed your HIDIdleTime line to one I use for this sort of thing.
I could not get you line to work, even on its own in terminal.

I got it from the main site! (http://www.macosxhints.com/article.php?story=20040330161158532&query=HIDIdleTime) Note that from the terminal you need to enter a sleep value or it will always come up zero because the idle time will be from when you hit enter/return.

Also noted you will not get a correct results if you use the () brackets around the HIDIdleTime line. as the result will return with brackets (40)
If you use the greater than symbol ">" and the brackets, it will not be picked up that what you are getting is not an integer expression.
I only got clued up on this when I change the symbol to -gt and got the error:
integer expression expected.
Anyway hope this helps.

I'll look into it, but it seemed to work for me.

Edit:
By the way, I like your idle time handler. I can understand it better than the sed, even though I usually find awk to be more confusing. ;)

mark hunte
01-12-2008, 04:50 AM
I got it from the main site! (http://www.macosxhints.com/article.php?story=20040330161158532&query=HIDIdleTime)

Even though the awk HIDIdleTime was also written for Tiger
The problem most likely with the sed HIDIdleTime are changes in Leopard breaking it.

cwtnospam
01-12-2008, 10:27 AM
If you use the greater than symbol ">" and the brackets,
I see what you mean about the > symbol.


Now I'm trying to make the password more secure, but I can't see a way of passing it from the shell script to the applescript without separating the two.

Tuxford
01-14-2008, 02:21 PM
Hi cwtnospam,
Just a thought, But how about merging the two scripts together into one shell script. Which get called by launchd.



I did not test the script below in lingon, but did test this in terminal and used a:
"sleep 40"
as the first line.

I also changed your HIDIdleTime line to one I use for this sort of thing.
I could not get you line to work, even on its own in terminal.
Also noted you will not get a correct results if you use the () brackets around the HIDIdleTime line. as the result will return with brackets (40)
If you use the greater than symbol ">" and the brackets, it will not be picked up that what you are getting is not an integer expression.
I only got clued up on this when I change the symbol to -gt and got the error:
integer expression expected.
Anyway hope this helps.


#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
EOT
fi
Tried to use Lingon in Tiger to create this, but it would not 'Load'. I entered each line - except the first line - as a separate program argument. Edited the password. Set the start interval to 60 seconds. Set to run at Load and On Demand. No luck. ???

cwtnospam
01-14-2008, 02:50 PM
It works for me. Some things to check:

Lingon should create a plist file that looks like the one below. You can check it by clicking the expert tab when editing the agent.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>agentto.switchuser.onidle</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/switchusershellname.sh</string>
</array>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>

The file: switchusershellname.sh needs to be executable. That means that if you type this command in a terminal window while in its directory:
ls -la

it should look like this:
-rwxr-xr-x 1 yourusername admin 456 Jan 12 17:34 switchusershellname.sh
If it doesn't, then type this in to the terminal while in that directory:
chmod 755 switchusershellname.sh


Edit: Note that it should also be a plain text file, so if you created it in TextEdit, you'll need to make sure it wasn't saved as an rtf file.

One more thing! Since it's only going to be executed from your admin account, and it will contain the password to your standard account, you probably want to store it in a folder that can't be read by other users, such as your documents folder, and you might as well set the permissions to 700 instead of 755. That will make it:
-rwx------
which is readable, writable, and executable only by its owner.

Tuxford
01-14-2008, 03:27 PM
I started again with your shell script from post #47, entered into Lingon:

It yields a valid:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>DualTrigger</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>idl=$((`ioreg -c IOHIDSystem | sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))</string>
<string>if [ $idl &gt; 30 ] </string>
<string>then</string>
<string>/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502</string>
<string>osascript</string>
<string>/Users/myusername/Library/ScriptingAdditions/AutologOff.app</string>
<string>fi</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>

It loads but never seems to trigger the AutoLogOff script. I have a previous shell 'run' script which will trigger the AutoLogOff script if loaded:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>Trigger AutoLogOff</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/myusername/Library/ScriptingAdditions/AutologOff.app</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>

cwtnospam
01-14-2008, 03:45 PM
I think you're confusing things that belong in the shell script with things that belong in Lingon.

Do it in this order:

1. Create a folder called Scripts in your documents folder.

2. Copy the code below into a new, plain text file. Save the file to your documents folder, in a folder called Scripts. Name the file: markswitch.sh

#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
EOT
fi


3. In a terminal window, type:
chmod 700 ~/documents/scripts/markswitch.sh

4. Open Lingon and create a new agent. Type everything in the Basic, and Miscellaneous tabs exactly as you see it in the pictures below, but change "username" to your username. The result should look like the Expert tab.

Tuxford
01-14-2008, 06:00 PM
Did exactly that, replacing the password. But nothing happens when loaded. Logged out and back in. Still nothing.

cwtnospam
01-14-2008, 06:15 PM
In a Terminal window type these commands and copy/paste the results back here:

cat ~/library/launchAgents/marks.switchuser.onidle.plist



cat ~/documents/scripts/markswitch.sh

By the way, a good way to test this is to use the wrong password in the script. That way, it should come up with the login screen, but not actually switch users on you!

Tuxford
01-14-2008, 06:34 PM
Ok, here it is except for edited names and passwords.

mydomain:~ myusername$ cat ~/library/launchAgents/marks.switchuser.onidle.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>marks.switchuser.onidle</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>Users/myusername/Documents/Scripts/Markswitch.sh</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>


mydomain:~ myusername $ cat ~/documents/scripts/markswitch.sh
{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440
{\fonttbl\f0\fmodern\fcharset77 Courier;}
{\colortbl;\red255\green255\blue255;\red245\green245\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\deftab720
\pard\pardeftab720\ql\qnatural

\f0\fs26 \cf0 \cb2 #!/bin/bash\
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ \{print int($NF/1000000000); exit\}'`"\
idletime="30"\
if [ $idl -gt $idletime ]; then\
/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502\
/usr/bin/osascript <<EOT\
delay 5\
tell application "System Events"\
keystroke "password" & return\
delay 4\
keystroke tab\
keystroke return\
end tell\
EOT\

cwtnospam
01-14-2008, 06:47 PM
First your plist shouldn't have RunAtLoad false in there. It may be happening because your shell script isn't right. See below.

Your shell script is wrong. I think you didn't save it as a plain text file. If you used TextEdit to create it, make sure it isn't using rtf as the format. If you look under the Format menu, it should not read "Make Plain Text" next to command-shift-T, because if it does, then you're in rtf. You need to select "Make Plain Text" and then save.
When you type:
cat ~/documents/scripts/markswitch.sh
in a terminal window, the file should look like this:

#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
end tell
EOT
fi


When you get these results by from the cat command, type this one again:

chmod 700 ~/documents/scripts/markswitch.sh

That should make the text file executable.

Maybe you can use the attached file below

Tuxford
01-14-2008, 09:17 PM
Got this this time:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>marks.switchuser.onidle</string>
<key>ProgramArguments</key>
<array>
<string>/Users/myusername/Documents/Scripts/Markswitch.sh</string>
</array>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>

Shouldn't I check 'OnDemand' under Basic?

Can I run your file (Password updated) directly in Terminal? Want to check functionality.

Could it be that the other user in the background is not idle? (It is running a Calendar Server application.)

cwtnospam
01-14-2008, 09:36 PM
It looks like it should work. You don't need OnDemand checked.

You could try the script from the terminal by typing this in a Terminal window:
sleep 62;/users/username/documents/scripts/markswitch.sh

You need to not touch the keyboard or mouse after hitting return, or the script might not get an idl that's greater than 30, in which case it won't bring up the login screen.

One more thing. Type this into a terminal window and post the results:

ls -la ~/documents/scripts/markswitch.sh

Tuxford
01-15-2008, 12:31 PM
Ran markswitch.sh successfully from terminal. It changed users.

But the lingon agent is not working.

mydomain:~ myname$ ls -la ~/documents/scripts/markswitch.sh
-rwx------ 1 myname myname 406 Jan 14 18:06 /Users/myname/documents/scripts/markswitch.sh

Tuxford
01-15-2008, 12:36 PM
Suddenly it starts working after I edited the agent arguments, changing the case of the file from Markswitch.sh to markswitch.sh.

cwtnospam
01-15-2008, 01:00 PM
Sorry I didn't see that. :o
I'm glad it's working though!

Tuxford
01-15-2008, 01:06 PM
Beats me why it fixed it. The filename is Markswitch.sh. Maybe some bad character was hidden in there. Anyway, can't thank you enough. I needed this one!

Tuxford
01-15-2008, 04:28 PM
I have noticed that on occasion, the script hangs at the login window. I guess the password is not passed correctly. Can the script be made more reliable? Can I include some check test, so that the script will repeat if not executed properly?

cwtnospam
01-15-2008, 04:38 PM
Does it enter the password and hang there? If so, you might add a delay and another keystroke return:

#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
keystroke return
delay 1
keystroke return
end tell
EOT
fi

I'd also disable any screen savers in this account since you don't want them competing.

cwtnospam
01-15-2008, 04:43 PM
Another possibility is that there needs to be a delay between the tab and the return:

#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
tell application "System Events"
keystroke "password" & return
delay 4
keystroke tab
delay 1
keystroke return
end tell
EOT
fi

Tuxford
01-16-2008, 06:44 PM
Added the delay plus another delay and return, for good measure. Seems to be purring. Now for another tweak.

How about I run the switchuser.onidle Agent only at the end of the day when I am going home? In Lingon, under the Misc tab, I put 18 in the hour box and hope for the best???

It would be nice if it would then stop running when I switch back in, at least again until 6 PM.

cwtnospam
01-16-2008, 08:19 PM
You could do that, but I think I'd run it this way at 6:00pm:

#!/bin/bash
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 2
tell application "System Events"
keystroke "password" & return
delay 2
keystroke tab
delay 2
keystroke return
end tell
EOT

Six seconds after 6, and you're in the other account!

Tuxford
01-17-2008, 01:18 PM
Reliability still not fixed. Noticed this AM that it did not switch users last night. It was again stuck at the Password entry window. Also noticed that the caps lock button was set to all CAPs. Think this is the issue. What can be done?

cwtnospam
01-17-2008, 02:45 PM
Don't use all caps? Unfortunately, it uses Applescript's gui scripting to enter the password. I don't know a way to force it to be lower case.

mark hunte
01-21-2008, 07:42 PM
I found a way of getting the system to ignore the CAPS LOCK, by changing the Keyboard layout temporarily, but the login window always changes it back to the normal one when it pops up, and then when closed flips back again. So I gave up. I also discovered that you can just click the login button by name.
And even though I also found out the Text Field name for the password, I could not write straight to it.(bummer)

do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
tell application "System Events"
delay 1
keystroke "password"
delay 1
click button "Log In" of window 1 of application process "SecurityAgent"
end tell

Tuxford
01-23-2008, 01:42 PM
Thanks Mark. Made the “click button” modification and working so far. Also set two agents in Lingon as triggers: one set “on idle”, and one set @ 6 PM (when I leave). However, still if I left the caps lock key depressed, the process is halted. So, maybe I need an “in your face” alert that the caps key is depressed? Maybe something that flashes the screen every 30 seconds?

I already use the shareware “Caps Warn”, but the it's alerts are not repetitive, but simply one time on event. Need something repetitive. Any ideas? Thanks.

mark hunte
01-23-2008, 07:32 PM
I can not believe I actually got this to work, But on a hunch I went looking for the app that runs the keyboard viewer.
Using the terminals find.. I found KeyboardViewerServer.app

/System/Library/Components/KeyboardViewer.component/Contents/SharedSupport/KeyboardViewerServer.app

This script (10.5.x(leopard only)) notifies you if the Caps lock is on or off
It calls the KeyboardViewerServer.app and checks the value of the keyboard viewer window, but heres the really (strange) good thing. even if the keyboard viewer window is not actually showing, the value still gets returned

If the CAPS is on the a growl notification pops up. You will need Growl.

(I did try and see if clicking the checkbox "⇪" would turn CAPS off, but no such luck)

--/System/Library/Components/KeyboardViewer.component/Contents/SharedSupport/KeyboardViewerServer.app

set appName to "Caps_lock_State"
set notificationName to "Caps_lock_State"
set notifs to {notificationName}
tell application "System Events"
tell application "KeyboardViewerServer" to activate
set CAPS to (get value of checkbox "⇪" of window 1 of application process "KeyboardViewerServer") as number
if CAPS is 1 then
my growl(CAPS, appName, notifs, notificationName)
end if
end tell
on growl(CAPS, appName, notifs, notificationName)
tell application "GrowlHelperApp"
register as application appName all notifications notifs default notifications notifs
end tell
set CAPS to "CAPS LOCK IS ON"
tell application "GrowlHelperApp"
notify with name notificationName title "CAPS LOCK IS ON" description CAPS application name appName
end tell

end growl

Tuxford
01-23-2008, 07:45 PM
Great! But I am still an amateur, so need a bit of guidance to make it run. My idea would be to drop this code in a BinBash script similar to the idle script above which after a short delay switches the user. This script would then just check the caps key state. Then would use Lingon to set up an agent to call it periodically.

So can you show how I would insert this code in the code of post #67? Thanks.

mark hunte
01-24-2008, 01:13 PM
**WARNING
Do NOT use or run the following script if you think you might be susceptible to photoepileptic seizures **

Here is another one that inverts the screen. The effect is a rapid double flashing of the screen. Then a pause,(5 seconds in this case) and then a another double flash. This will continue until the Caps lock is released
(* ** WARNING
Do NOT use or run the following script if you think you might be susceptible to photoepileptic seizures ] **)
tell application "System Events"
tell application "KeyboardViewerServer" to activate
set CAPS to (get value of checkbox "⇪" of window 1 of application process "KeyboardViewerServer") as number
if CAPS is 1 then
repeat until CAPS is 0
set CAPS to (get value of checkbox "⇪" of window 1 of application process "KeyboardViewerServer") as number
my invert(CAPS)
end repeat
end if
end tell
on invert(CAPS)
repeat 4 times
tell application "System Events"
key code 28 using {command down, option down, control down}

end tell
end repeat
delay 5
end invert

Tuxford, tell me if both the script work first, and then which one you prefer to go into the script in post#67

mark hunte
01-24-2008, 03:52 PM
Although I am really Happy to have found a way to detect CAPS LOCK.

I just had another go at entering the password via set value.
I found the combination that got it to work :)
So now even if the CAPS LOCK is on the script should work.

set password_ to "password"
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
tell application "System Events"
delay 1
tell process "SecurityAgent" to set value of text field 1 of group 1 of window 1 to password_
click button "Log In" of window 1 of application process "SecurityAgent"
end tell

cwtnospam
01-24-2008, 04:30 PM
Good job! I was looking for a way to do it through the shell script. I think that there must be a way, but I haven't found it.

Tuxford
01-24-2008, 07:25 PM
Got an error running the script #77 in the script editor.

And got stuck each time at the dialog box running #78 called by Lingon. (I tried to plug it in my switchuser script). But #78 will run from the script editor. If I save it as an application and launch it, it yields an error.

Guess I would like #78 plugged into #67. But might like to experiment with #77 too a little later.

By the way, reminder that I am running Tiger.

mark hunte
01-25-2008, 02:31 AM
Thanks I will test on Tiger.
Can you post the error you where getting for #78 and #77

Tuxford
01-25-2008, 01:46 PM
For 77 within the script editor: Stuck on 'value', System events error msg “NsreceiverEvaluationScriptError: 4”. From the line “get value of checkbox "c" of window....” Where did “c” come from. I cut and paste. How do I get the right character for CapsLock in there?

For 78, I did some editing and got it to work. Don't know why, except probably just bad path argument? Now just need to fold this code in together with the idle time code from 68. Plugging it into the script editor doesn't work. I just don't know these rules.

mark hunte
01-25-2008, 05:16 PM
Hi, I have not been able to test this today, but I should have mentioned, paste the "⇪" into textedit and the copy it from there and paste it into the script. This is only needed for tiger.


Is this what you are after
#!/bin/bash
idl=$"`ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print int($NF/1000000000); exit}'`"
idletime="30"
if [ $idl -gt $idletime ]; then
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
set password_ to "password"
tell application "System Events"
delay 1
tell process "SecurityAgent" to set value of text field 1 of group 1 of window 1 to password_
click button "Log In" of window 1 of application process "SecurityAgent"
end tell
EOT
fi

Tuxford
01-25-2008, 05:47 PM
Pasting from Textedit into the Script Editor doesn't work, since it changes it back to “c” upon compilation. Need another idea here.

Got #83 to work! Thanks.

Tuxford
01-25-2008, 08:15 PM
If you are up to it!

Need also to automatically start my private user upon startup, since it runs some scheduled backups. Is there a way to start up user 501 in the background, rather than logging in? If not, is there a way to make user 501 immediately switch back to 502 upon this special startup condition only?

cwtnospam
01-26-2008, 05:23 PM
Easy! Auto boot into user 501 and set a copy of the script to run in it using Lingo, but set the idletime to be small, the switchToUserID to be 502, and call the script after 3 or 4 minutes.

mark hunte
01-27-2008, 07:14 AM
Pasting from Textedit into the Script Editor doesn't work, since it changes it back to “c” upon compilation. Need another idea here.


I thought That had worked when I tried it, but obviously I must have dreamt it?

It looks like there is a bug in 10.4's Applescript, which see's the unicode text for Caps as a "c"


Any way those scripts that use the Caps Lock detection will Not work in 10.4
The 10.4 "KeyboardViewerServer" does not have a value for the Caps Lock to be returned

Tuxford
01-29-2008, 07:36 PM
Bad news on Tiger. Thanks.

Can't seem to get any 'My Agent' to run right now? Even created a new one with the assistant to Keep an Application Running, but it does work either. What could be wrong? Logged out and back in. Dead. Why isn't Lingon reliable? How to check status?

cwtnospam
01-29-2008, 07:51 PM
Lingon is very reliable. If it isn't working, there must be an error in your script. Post that, along with the plist that Lingon creates.

Tuxford
01-29-2008, 07:58 PM
My server machine finally just crashed. Restarted and agents seems to be running now. Think this error condition persisted over the weekend without notification. Not good. Now need an alert when the Agents are down! Any ideas?

cwtnospam
01-29-2008, 08:03 PM
Well, for that you'd need an agent, which wouldn't run if the agents were down. Unless you want it to continuously notify you that it is running, I don't think you can do that.

Tuxford
01-29-2008, 08:37 PM
Well, it seems that when I restarted the server, all was running. But then I logged out of the admin user, and immediately logged back in. Since then, no agents seem to be running? Repeating the login does not help...

Should I remove Growl? I installed it per a suggestion above. I removed it.

Finally, wonder if these switch agents should be My Agents or Users Agents? Found that a KeepUp agent runs under Users Agents, but will not run under My Agents.

Confusing: Where are the preferences located for an application launched under Users Agents? Certainly is not in the My Agents users home preferences folder.

Now restarted this server which comes up as the standard user, and switched users to the admin user (a login). My Agent set to run OnLoad, ran, and brought up the short-idle switch dialogue, and switched users. I switched back and repeated. It again attempted to switch back, but I hit the cancel button and then logged out to the blue screen. Logged back in as the admin user, and now the OnLoad switch agents are not running???? Ugh! (Checked idle agents. They are not running either.) Brought up Lingon, and that agent is no longer loaded. So loaded it and logged out. Logged back in and same problem in Lingon. So I conclude that I must never log out after a restart and login as admin. What am I missing? Logging out disables the 'My Agents' until restart.

Tuxford
08-08-2008, 07:48 PM
Although I am really Happy to have found a way to detect CAPS LOCK.

I just had another go at entering the password via set value.
I found the combination that got it to work :)
So now even if the CAPS LOCK is on the script should work.

set password_ to "password"
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502"
tell application "System Events"
delay 1
tell process "SecurityAgent" to set value of text field 1 of group 1 of window 1 to password_
click button "Log In" of window 1 of application process "SecurityAgent"
end tell

I am now getting an applescript error running this script under Tiger 4.11. When I run this I get a System Events error message “NSReceiverEvaluationScriptError: 4”. I need this script again, but am now stuck. It worked before, as I had it saved and was using a saved app version of it. Thanks in advance. See post #78.

cwtnospam
08-08-2008, 09:17 PM
I am now getting an applescript error running this script under Tiger 4.11. When I run this I get a System Events error message “NSReceiverEvaluationScriptError: 4”. I need this script again, but am now stuck. It worked before, as I had it saved and was using a saved app version of it. Thanks in advance. See post #78.

I just tried it by copy/pasting exactly as you posted it on my machine (10.4.11) and it worked fine. It failed on the password, but that's to be expected. ;)

Do you have a user with ID 502?
You can run this Applescript to find out:
set x to do shell script "nidump passwd . | grep 'Users'"
display dialog x

Tuxford
08-13-2008, 01:49 PM
I just tried it by copy/pasting exactly as you posted it on my machine (10.4.11) and it worked fine. It failed on the password, but that's to be expected. ;)

Do you have a user with ID 502?
You can run this Applescript to find out:
set x to do shell script "nidump passwd . | grep 'Users'"
display dialog x

That hint was enough. Used Sharepoints to change the user ID to 502. Got it to work with and old bin bash script I used before, with Lingon calling it on 'idle'. However, need another call on 'login', which I can't seem to get Lingon to load.

On Idle call is periodically every several minutes. However, my mail server must start up initially to a protected admin user in order to launch a backup program, and then immediately switch to a standard user for security. I would like Lingon to therefore call this same bash script immediately upon login. Can't figure why 'Run at Load' checkbox doesn't allow it to work. Reminder: using Tiger.

cwtnospam
08-13-2008, 03:12 PM
However, need another call on 'login', which I can't seem to get Lingon to load.
What are you trying to call at login?

Tuxford
08-13-2008, 03:18 PM
What are you trying to call at login?

The very same script (post #93) as the idle handler calls. I have added a few extra seconds delay in that script though. When I restart the machine, it logs into the admin user, and after the idle time, switches user. However, I am trying to get it to switch almost immediately with an additional Lingon Agent that 'runs at load'.

cwtnospam
08-13-2008, 05:08 PM
I think you need the one from post#83, but that's a shell script, not an Applescript.

Tuxford
08-13-2008, 05:13 PM
I think you need the one from post#83, but that's a shell script, not an Applescript.

I am sorry. I got confused. It is the one from #83 that I am calling using Lingon.

cwtnospam
08-13-2008, 06:32 PM
The way it's written, the system would have to have been idle for more than 30 seconds when the script is first called. That's unlikely to happen right at startup. I suggest you save the script below as a different script and have Lingon call it at startup. You'll have 6 seconds after the login screen pops up to cancel the switch if you need to stay in the account.

#!/bin/bash
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 502
/usr/bin/osascript <<EOT
delay 5
set password_ to "password"
tell application "System Events"
delay 1
tell process "SecurityAgent" to set value of text field 1 of group 1 of window 1 to password_
click button "Log In" of window 1 of application process "SecurityAgent"
end tell
EOT

Tuxford
08-13-2008, 09:41 PM
Still could not get Lingon to call your bash script above upon restart. Tried different combinations of 'Run at Load' and 'On Demand' checkboxes.

Found another way! Using applescript in post #78 as a login item. It includes a short delay in case I want to cancel. Thanks!