I'm using OS X 10.6.5 and occasionally access it via ssh. While accessing it this way I need to be able to use the screencapture utility to take an image of the screen. The man page for screencapture says to do the following, but this doesn't seem to work for me:
SECURITY CONSIDERATIONS
To capture screen content while logged in via ssh, you must launch
screencapture in the same mach bootstrap hierarchy as loginwindow:
PID=pid of loginwindow
sudo launchctl bsexec $PID screencapture [options]
The command I'm using currently is:
sudo launchctl bsexec 53 screencapture foo.png
The result is that no PNG is outputted and the command silently returns. Can any of you help me make this work? Thanks!
Try logging in via ssh to the same username currently logged in at the OS X main display. You should then be able to run screencapture directly in the ssh session.
Maybe this "gist" helps: https://gist.github.com/323256
#!/usr/bin/env bash
screenshot="screnshot.png"
screencapture='/usr/sbin/screencapture -xC'
if [ `whoami` == 'root' ]; then
loginpid=`ps -ax | grep [l]oginwindow.app | awk '{print $1}'`
launchctl bsexec $loginpid $screencapture $screenshot
else
$screencapture $screenshot
fi
Related
I'm trying to write my own .tmux.config file and have managed to get most of it working (the file is quite simple). The intention is to have a minicom session running on the right side, whilst simultaneously saving the communication into a file. There is one problem. I define a UART_LOGFILE_NAME variable in my .bashrc file and export it, however, tmux still returns invalid environment variable. Is there something I'm missing?
my .tmux.conf file looks somewhat like this:
new-session -s serial -n console
split-window -h -l 30%
send-keys "sudo minicom rasp.serial -C ${UART_LOGFILE_NAME}"
split-window -v -l 10%
I can't find anything relevant in tmux manual entry except for the GLOBAL AND SESSION ENVIRONMENT. Also, sice I'm using the send-keys command I thought that the .bash_profile and therefore .bashrc files have been sourced before the minicom is launched (I have already managed to get the minicom running without logging and all panes have the UART_LOGFILE_NAME variable correctly defined after when I run tmux without logging of minicom session).
Thank you for your help
First, I create a session by typing screen -S test1, then I detach and type screen -S test1 -p 0 -X stuff "ls^M". This doesn't work, it just prints the characters "ls^M" in my session.
Without more details I don't know why it does not work for you but you can try other ways:
screen -S session -X -p 0 stuff "echo hello\r"
# OR
screen -S session -X -p 0 stuff $'echo world\r'
Another solution (from #pynexj) is to simply update the screen shipped with MacOS:
brew install screen
Then restart the terminal.
Ok everyone, here is an issue which bugged me for quite some time now:
I am trying to run a bash script, which stores certain values in variables, and then starts another command in a detached session, so that the script can continue running because the command takes ages to finish. That's all fine and nice, but the problem is that the command which should be run in the detached session contains variables. This is not a problem when using screen as the "session manager" (or whatever you want to call a program doing session management):
read -p "Session name:" sessionname
read -p "Filename:" filename
screen -S "$sessionname" -d -m nano "$filename"
works fine, opening nano in the detached screen as expected. But when i re-attach to the session and close it, my terminal is cleared and sometinmes some of the text from the file is barfed right before my cursor. I realized that this is an issue with how screen works, so i decided to switch to tmux, but now a whole new realm of prblems opens:
tmux new-session -d -s "$sessionname" nano "$filename"
works fine on cygwin, but on my raspberry 2b running raspbian jessie it throws this error:
usage: new-session [-AdDp] [-c start-directory] [-F format] [-n window-name] [-s session-name] [-t tar
get-session] [-x with] [-y height] [command]
and trying tmux ls afterwards to see if anything started gives me this on the raspberry:
failed to connect to server: No such file or directory
while on cygwin, if no sessions are running, it gives me this:
no server running on /tmp/tmux-197609/default
How can it be that tmux on two different plattforms behaves conmpletely different? Have i installed it wrong on the raspberry (sudo apt-get install tmux) ?
I am all out of ideas what might be the problem here, so any help is greatly appreciated. (Sorry for confused spelling & grammar, non-native english speaker here)
We can run something like chsh -s /usr/local/bin/zsh to set a new default shell. Is there a command we can run to know what that shell is?
I don’t mean having a terminal open and running a command to know which shell we’re in. I mean like in the example above, if I’m in a terminal with /bin/bash open, what should I run to get /usr/local/bin/zsh if it’s the current default shell?
You can use the following command:
echo $SHELL
For macOS:
dscl . -read /Users/username UserShell
For the current macOS user:
dscl . -read ~/ UserShell
To parse the path inline using sed:
dscl . -read ~/ UserShell | sed 's/UserShell: //'
Using $SHELL will report the current login shell, not the default login shell. In certain cases, these are not the same. For example, when working in an IDE such as Visual Studio Code which opens an integrated terminal without consulting the default shell.
In addition, as pointed out by Martin C. Martin, $SHELL is a constant that will not change after chsh changes the default login shell.
You can grep in the /etc/passwd file for current username, and use cut to extract the appropriate column of information:
grep ^$(id -un): /etc/passwd | cut -d : -f 7-
$(id -un) is a safer than $USER to get user name. Using ^ in front of user name and : after makes sure you don't get a false match if your user name is a sub section of someone else user name.
$SHELL can also be used, as suggested. However it won't work if chsh was used in current shell, as the variable is not updated. Also the variable is not protected against being changed, so it can theoretically be set to something completely different.
Update to attempt an OS X compatible solution. Probably not optimal regexp:
grep ^.*:.*:$(id -u): /etc/passwd | cut -d : -f 7-
This is based on user id's. If the whole user entry is missing, not only user name, then osx must store this somewhere else.
If you want to get the default shell of a user, you could grep file /etc/passwd. like:
grep "$USER" /etc/passwd
# kent:x:1000:1000::/home/kent:/bin/zsh
telling me that the current user (kent) has the default shell /bin/zsh.
If you just want to catch the shell part:
awk -F: -v u="$USER" 'u==$1&&$0=$NF' /etc/passwd
# /bin/zsh
If you want to get the default shell of other user, just replace the $USER part.
In OS X, using the command env | grep -i 'SHELL' produces an output such as: SHELL=/bin/sh
(as root, however regular users tend to have /bin/bash as default shell) with a little parsing, the path the shell (and thus the shell itself) could be easily identified and extracted from there..
Did anyone succeed in setting up automated UIAutomation tests in Xcode?
I'm trying to set up a target in my Xcode project that should run all the UIAutomation scripts I prepared. Currently, the only Build Phase of this target is this Run Script block:
TEMPLATE="/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"
MY_APP="/Users/Me/Library/Application Support/iPhone Simulator/6.0/Applications/564ED15A-A435-422B-82C4-5AE7DBBC27DD/MyApp.app"
RESULTS="/Users/Me/Projects/MyApp/Tests/UI/Traces/Automation.trace"
SCRIPT="/Users/Me/Projects/MyApp/Tests/UI/SomeTest.js"
instruments -t $TEMPLATE $MY_APP -e UIASCRIPT $SCRIPT -e UIARESULTSPATH $RESULTS
When I build this target it succeeds after a few seconds, but the script didn't actually run. In the build log I get these errors:
instruments[7222:707] Failed to load Mobile Device Locator plugin
instruments[7222:707] Failed to load Simulator Local Device Locator plugin
instruments[7222:707] Automation Instrument ran into an exception while trying to run the script. UIATargetHasGoneAWOLException
+0000 Fail: An error occurred while trying to run the script.
Instruments Trace Complete (Duration : 1.077379s; Output : /Users/Me/Projects/MyApp/Tests/UI/Traces/Automation.trace)
I am pretty sure, that my javascript and my run script are both correct, because if I run the exact same instruments command in bash it works as expected.
Could this be a bug in Xcode?
I finally found a solution for this problem. It seems like Xcode is running the Run Scripts with limited rights. I'm not entirely sure, what causes the instruments command to fail, but using su to change to your user will fix it.
su $USER -l -c <instruments command>
Obviously, this will ask you for your password, but you can't enter it when running as a script. I didn't find a way to specify the password for su, however if you run it as root, you don't have to specify one. Luckily sudo can accept a password via the pipe:
echo <password> | sudo -S su $USER -l -c <instruments command>
If you don't want to hardcode your password (always a bad idea), you could use some AppleScript to ask for the password.
I posted the resulting script below. Copy that to a *.sh file in your project and run that script from a Run Script.
#!/bin/bash
# This script should run all (currently only one) tests, independently from
# where it is called from (terminal, or Xcode Run Script).
# REQUIREMENTS: This script has to be located in the same folder as all the
# UIAutomation tests. Additionally, a *.tracetemplate file has to be present
# in the same folder. This can be created with Instruments (Save as template...)
# The following variables have to be configured:
EXECUTABLE="TestApp.app"
# Optional. If not set, you will be prompted for the password.
#PASSWORD="password"
# Find the test folder (this script has to be located in the same folder).
ROOT="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Prepare all the required args for instruments.
TEMPLATE=`find $ROOT -name '*.tracetemplate'`
EXECUTABLE=`find ~/Library/Application\ Support/iPhone\ Simulator | grep "${EXECUTABLE}$"`
SCRIPTS=`find $ROOT -name '*.js'`
# Prepare traces folder
TRACES="${ROOT}/Traces/`date +%Y-%m-%d_%H-%M-%S`"
mkdir -p "$TRACES"
# Get the name of the user we should use to run Instruments.
# Currently this is done, by getting the owner of the folder containing this script.
USERNAME=`ls -l "${ROOT}/.." | grep \`basename "$ROOT"\` | awk '{print $3}'`
# Bring simulator window to front. Depending on the localization, the name is different.
osascript -e 'try
tell application "iOS Simulator" to activate
on error
tell application "iOS-Simulator" to activate
end try'
# Prepare an Apple Script that promts for the password.
PASS_SCRIPT="tell application \"System Events\"
activate
display dialog \"Password for user $USER:\" default answer \"\" with hidden answer
text returned of the result
end tell"
# If the password is not set directly in this script, show the password prompt window.
if [ -z "$PASSWORD" ]; then
PASSWORD=`osascript -e "$PASS_SCRIPT"`
fi
# Run all the tests.
for SCRIPT in $SCRIPTS; do
echo -e "\nRunning test script $SCRIPT"
COMMAND="instruments -t \"$TEMPLATE\" \"$EXECUTABLE\" -e UIASCRIPT \"$SCRIPT\""
COMMAND="echo '$PASSWORD' | sudo -S su $USER -l -c '$COMMAND'"
echo "$COMMAND"
eval $COMMAND > results.log
SCRIPTNAME=`basename "$SCRIPT"`
TRACENAME=`echo "$SCRIPTNAME" | sed 's_\.js$_.trace_g'`
mv *.trace "${TRACES}/${TRACENAME}"
if [ `grep " Fail: " results.log | wc -l` -gt 0 ]; then
echo "Test ${SCRIPTNAME} failed. See trace for details."
open "${TRACES}/${TRACENAME}"
exit 1
break
fi
done
rm results.log
It seems as though this really might be an Xcode problem; at any rate, at least one person has filed a Radar report on it. Someone in this other thread claims you can work around this exception by disconnecting any iDevices that are currently connected to the computer, but I suspect that does not apply when you're trying to run the script as an Xcode target.
I would suggest filing a Radar report as well; you may get further details on the issue from Apple, or at least convince them that many people are having the problem and they ought to figure out what's going on.
Sorry for a not-terribly-helpful answer (should have been a comment, but comments and links/formatting do not mix very well). Please update this question with anything you find out on the issue.
Note: this is not a direct answer to the question, but it is an alternative solution to the underlying problem.
While searching for in-depth information about UIAutomation, I stumbled across a framework by Square called KIF (Keep it functional). It is a integration testing framework that allows for many of the same features as UIAutomation, but the great thing about is is that you can just write your integration tests in Objective-C.
It is very easy to setup (via CocoaPods), they have good examples too, and the best thing is that it's a breeze to set up with your CI system like Jenkins.
Have a look at: http://github.com/square/KIF
Late to the game but I have a solution that works for Xcode 5.1. Don't know if that's what broke the above solution or not. With the old solution I was still getting:
Failed to load Mobile Device Locator plugin, etc.
However, this works for the release version of Xcode 5.1.
echo <password> | sudo -S -u username xcrun instruments
Notice I removed the unneeded su command and added the xcrun command. The xcrun was the magic that was needed.
Here is my complete command:
echo <password> | sudo -S -u username xcrun instruments\
-w "iPhone Retina (3.5-inch) - Simulator - iOS 7.1"\
-D "${PROJECT_DIR}/TestResults/Traces/Traces.trace"\
-t "${DEVELOPER_DIR}/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"\
"${BUILT_PRODUCTS_DIR}/MyApp.app"\
-e UIARESULTSPATH "${PROJECT_DIR}/TestResults"\
-e UIASCRIPT "${PROJECT_DIR}/UITests/main.js"
By the way if you type:
instruments -s devices
you will get a list of all the supported devices you can use for the -w option.
Edit: To make this work for different people checking out the project replace the following:
echo <password> | sudo -S -u username xcrun instruments
with
sudo -u ${USER} xcrun instruments
Since you are just doing an sudo to the same user no password is required.
Take a look at this tutorial that explains how to have Automated UI testing with Jenkins. It also uses Jasmine in the tutorial though. http://shaune.com.au/automated-ui-testing-for-ios-apps-uiautomation-jasmine-jenkins/ hope this helps. It has an example project file so you can download that as a template. Hope this helps.
In XCode - if you load up organizer (XCode->Window->Organizer)
Then select your machine under devices -> 'Enable Developer Mode'
This should remove the need for prompts with instruments.