Get rid of your busy life and start with automation. As a professional, have you ever been worried about forgetting to send a report email? Have you ever lost everything because of busy work? As a programmer, have you ever been annoyed by the long compile time after pulling code every morning, or bored by the various mindless system configurations? Every day we waste our precious lives doing these repetitive, boring things. How to improve work efficiency has become a very important thing for us. This document will lead us to improve our work efficiency effectively by means of automation.
Most of this article is based on the MacOS environment, and non-Mac people can borrow some of the ideas.
Shell Script
The Shell and the Shell Script
Before we talk about automation, let’s take a look at Shell Script, an ancient and very powerful scripting language. First, we need to clarify a conceptual question, the difference between Shell and Shell Script:
A Shell is an application that provides an interface through which the user accesses the services of the operating system kernel.
A Shell Script is a Script program written for the Shell.
Just to give you a sense of the concept, but most of the time, we refer to Shell Script as Shell, and “Shell” in other parts of the text also means Shell Script. The basic syntax of the shell is beyond the scope of this article, but before I start practicing how the shell can improve our productivity, LET me briefly introduce a few common and powerful features of the shell.
Common series command
The pipe
Pipes are one of the most common features of the shell. They allow different scripts and commands to pass data to each other. For example:
ls | grep 'pars'
Copy the code
This command means to pass the ls output to grep ‘pars’, grep will filter out the contents containing ‘pars’. Get the current branch name in git repository by shell:
currentBranch=`git branch | grep "*"`
currentBranch=${currentBranch/* /}
Copy the code
redirect
Most UNIX system commands accept input from the terminal and send the resulting output back to the terminal. A command usually reads input from a place called standard input, which by default is terminal. Similarly, a command usually writes its output to standard output, which is also terminal by default. If you need to modify the input or output, you need to use redirection.
The command | instructions |
---|---|
command > file | Redirect output to file. |
command < file | Redirect input to file. |
command >> file | Redirect output appending to file. |
Output redirection refers to redefining the input position of a command, for example:
ls > ls.txt
Copy the code
The ls output should be displayed on the terminal, and the command writes the ls output to the ls.txt file. Note that using > redirection to ls. TXT files overwrites by default. If you want to append files, use >> :
pwd >> ls.txt
Copy the code
Input redirection:
pbcopy < ls.txt
Copy the code
The command above means to copy the contents of ls.txt to the stickboard.
The reason for this brief introduction is that if you don’t understand these functions, it will affect your understanding of the following content. If you are not familiar with shell scripts, it is recommended that you take some time to learn them. Shell is often used in daily work.
Practice is the sole criterion of learning
After a brief talk about shell’s several common and powerful functions, we began to practice how to improve work efficiency through shell.
Automatic configuration of two nics
Due to my daily work, the computer needs to be configured with dual network adapters. Here is an example of configuring dual network adapters on the computer. Some configuration scripts are attached first:
inside_ssid=\"WIFINAME\";
en0_ssid=\"$(networksetup -getairportnetwork en0 | sed 's/.*[:] //')\"
if [ \"$en0_ssid\ "! = \"$inside_ssid\] "; Then echo -n \$inside_ssid\"
else
inside_adaptor_index=\"$(netstat -rn|grep default |grep en0 -n | cut -d: -f1)\"
if [ \"$inside_adaptor_index\ "= 1]; Then echo -n \" start external nic \" else inside_gateway=\"$(netstat -rn|grep default |grep en0|awk '{print $2}')\" sudo echo \" refresh configuration successfully \"; sudo route -n delete -net 10.*.*.128; sudo route -n delete -net 10; sudo route -n delete -net 30; sudo route -n add -net 10.*.*.128$inside_gateway;
sudo route -n add -net 10 $inside_gateway;
sudo route -n add -net 30 $inside_gateway
fi
fi
Copy the code
Instead of parsing what these scripts do, we’ll focus on how to further improve efficiency. Each time the COMPUTER is restarted, you need to reconfigure the dual NETWORK adapters so that the Internet and extranet can be used at the same time. In other words, you need to perform this operation again each time the computer is restarted. It’s human nature to be lazy, so if we don’t even want to execute a script, what do we do?
We can set the self-start task when the computer is turned on. First I need to create a plist file:
<?xml version="1.0" encoding="UTF-8"? >
<plist version="1.0">
<dict>
<key>LaunchOnlyOnce</key>
<true/>
<key>Label</key>
<string>com.dengyonghao.xxxx</string>
<key>ProgramArguments</key>
<array>
<string>/Users/xxxxx/work/Tools/xxxx.sh</string>
</array>
</dict>
</plist>
Copy the code
LaunchOnlyOnce specifies that the LaunchOnlyOnce command is executed only once upon startup. If the LaunchOnlyOnce command is not specified, the LaunchOnlyOnce command is executed once at intervals. Label Specifies the unique identifier of the PLIST. ProgramArguments sets the path of the script to be executed, pointing to the path of the script that you want to be executed automatically at startup.
After doing the above, copy the plist file to the ~/Library/LaunchAgents directory, indicating that it only works for the current user, then execute:
sudo launchctl load ~/Library/LaunchAgents/xxxxxx.plist
Copy the code
Register this file with the system and it will be executed automatically when the computer boots up to complete the dual network configuration. Here is a question, if the above dual nic configuration script is automatically executed on startup, will it really work?
In fact, no, because sudo requires you to enter the administrator password, but you don’t have anywhere to enter it, so you don’t have permission to do that. Therefore, we need to use Apple Script to introduce the content of the next section. Here is the Apple Script:
do shell script "
inside_ssid=\"WIFINAME\";
en0_ssid=\"$(networksetup -getairportnetwork en0 | sed 's/.*[:] //')\"
if [ \"$en0_ssid\ "! = \"$inside_ssid\] "; Then echo -n \$inside_ssid\"
else
inside_adaptor_index=\"$(netstat -rn|grep default |grep en0 -n | cut -d: -f1)\"
if [ \"$inside_adaptor_index\ "= 1]; Then echo -n \" start external nic \" else inside_gateway=\"$(netstat -rn|grep default |grep en0|awk '{print $2}')\" sudo echo \" refresh configuration successfully \"; sudo route -n delete -net 10.*.*.128; sudo route -n delete -net 10; sudo route -n delete -net 30; sudo route -n add -net 10.*.*.128$inside_gateway;
sudo route -n add -net 10 $inside_gateway;
sudo route -n add -net 30 $inside_gateway
fi
fi" with administrator privileges
Copy the code
Apple Script is simply used to provide a graphical interface that requires the user to enter an administrator password before allowing him to continue executing the Script. The Script uses Apple Script, so the plist file of boot item should also be changed accordingly:
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/xxxx/work/Tools/xxxx.scpt</string>
</array>
Copy the code
The Apple Script will be covered in the next section, but let’s start with a question: Will the pain points above be resolved once you set it to boot?
In fact, not all problems can be solved. For example, when the external network card is not plugged in when the boot is started, the script automatically executed will fail to configure, and then it will return to the original scene. We need to find the script file and execute it through the terminal. So how can we optimize this process? Let’s take this problem, move on, and then come back and solve it.
brainstorm
In the process of sharing with team members, team members suggested that sudo can set the administrator password in clear text, which does not need to be manually entered each time it runs. The command format is as follows:
echo password | sudo -S xxxxxxxxx
Copy the code
Note that passwords saved in plaintext may be leaked. You are advised to evaluate the risks before using this method.
Apple Script
What is Apple Script?
AppleScript is a scripting language created by Apple to automate the operations of the Macintosh operating system and many of its applications. It can be used to control programs running on macOS, as well as parts of macOS itself. You can create scripts to automate repetitive tasks, or combine the capabilities of multiple scriptable applications to create complex workflows.
We use AppleScript to create memos, manage networks, process images, back up files, and much more. AppleScript is a very powerful automation tool built into macOS, written and run through script editor applications, and available to any user for free.
Script editor
A tool for writing AppleScript is already available in macOS by default: the script editor, which you can find and start in your application.
Our first AppleScript script
Let’s open the script editor and select New Document and type the following:
tell application "Finder" to open the startup disk
Copy the code
When you hit Run, a new Finder window opens on the desktop, showing the contents of the boot drive, and here we’ve finished our first AppleScript script.
For another example, turn Xcode on or off with AppleScript:
tell application "Xcode"
activate
--quit
end tell
Copy the code
As you can see from the script above, AppleScript is very similar to a natural language and is very simple to write. However, there is no tutorial on how to learn AppleScript syntax.
How do I learn AppleScript
Use opportunely document
Dash, one of the programmer’s wonders, strongly recommends a wave.
When we’re learning a new programming language, when we have a problem using an API, the most reliable solution is not Google, but the documentation. Dash allows you to download AppleScript documents and quickly look them up when you encounter problems. AppleScript documents are not very large, so you can read through them once in your spare time (estimated at 2-3 hours) to gradually deepen your understanding of AppleScript.
Understand AppleScript Dictionary
Practice is the mother of wisdom
Report mail reminders & automatically generated
In addition to the notification function, the tool will also automatically help you to create a mail module, including the recipient, subject, content template, etc. Let’s look at the implementation script:
on callback()
tell (current date) to get (its year as integer) & "-" & (its month as integer) & "-" & day
set dataText to the result as text
set mailTitle to "- Progress of key projects" as text
set mailTitle to dataText & mailTitle
tell application "Microsoft Outlook"
set newMessage to make new outgoing message with properties {subject:mailTitle, content:
Best Regards"}
make new recipient at newMessage with properties {email address:{name:"xxx", address:"[email protected]"}}
#make new cc recipient at newMessage with properties {email address:{name:"Name", address:"[email protected]"}}
open newMessage
end tell
end callback
display dialog "It's Monday again. Let's send you progress on key projects." buttons {"Send it now"."In a moment."} default button 1
if the button returned of the result is "Send it now" then
callback()
end if
Copy the code
Here we use AppleScript to access Microsoft Outlook and automatically generate email templates. The above script only fills the module with the email content, but it can actually automatically attach your key project progress to the Excel spreadsheet. You can use AppleScript to read the excel content directly and fill it into your email. As long as you update the Excel spreadsheet after finishing your key items, you can automatically send your key items every Monday with a single command.
After we complete the function of automatically generating mail template, we also need to provide the function of automatic reminder. As for the function of automatic reminder, we can use the MAC startup service to realize it, which is the same as the way of automatic configuration of dual network, we create the corresponding PList file:
<?xml version="1.0" encoding="UTF-8"? >
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.dengyonghao.viproject</string>
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/dengyonghao/work/Tools/viproject.scpt</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>1</integer>
<key>Minute</key>
<integer>30</integer>
<key>Hour</key>
<integer>10</integer>
</dict>
</dict>
</plist>
Copy the code
StartCalendarInterval this key is used to control the execution period or time of your scripts. The script will be automatically executed every Monday at 10:30 am.
AppleScript is very powerful. We recommend you to discuss how to use AppleScript together.
Recommended reading
- Mac Automation Scripting Guide
Automator
What is an Automator?
Automator is apple’s macOS software that lets you perform complex tasks automatically (and repeatably) by combining a series of actions into a workflow by clicking, dragging and dropping a mouse. Automator is actually a series of actions grouped together in a workflow document and executed sequentially. It’s very similar to the script above, but Automator can be performed across multiple applications and provides a graphical interface that makes it very easy for users to use.
Script to Application
Start macOS Automator, choose New Document > Applications > Utilities > Run XXX script, fill in your script, and save to create an application. The default generated app is the Automator icon. If you want to change the icon, right-click Apps > Show package Contents >Contents >Resources and replace automatorApplet.icns with the desired icon.
It would be nice to be able to take a common script generation application, put it in a common location, and double-click on it, but that’s not what I wanted. I wanted it to be quick in any method, so HERE’s where Alfred came in.
Recommended reading
There are many tutorials about Automator online, want to further understand students, recommended reading: Automator brief introduction and an introduction to play | Matrix selection
Alfred & WorkFlows
What is Alfred? But I’m not going to tell you how to use Alfred.
Workflow is a process that combines multiple events together to form a coherent action.
Self learning
Thousands of words are omitted here, and you’ll have to learn how Alfred uses it, and maybe it’s –>GoogleCan help you
Issue review
At this point, we can think about the problem that the article began to configure dual network card, I guess everyone will have a better way.
We can write AppleScript configured with dual network cards as a workflows of Alfred. For example, I set Alfred’s shortcut open key to double com and the keyword for workflows to doublenet, so THAT I could type in any interface on my computer: Double COM + Doublenet + Press Enter to complete the configuration of dual network adapters.
A pot of stew
This is a bunch of tools, and you might not know what to do with them, but let’s put them to the test.
Goto iTerm
As a programmer, there are a lot of scenarios to jump from Finder to iTerm, and most of the time we just drag directories to iTerm and CD into it, which is very inefficient, and by learning this, We can quickly open the current Finder’s directory in iTerm with AppleScript + Hotkey.
First we can get the directory of the current Finder window with AppleScript:
tell application "Finder"
set pathFile to selection as text
setPathFile to get POSIX path of pathFile -- Prevents directories from jumping if there are Spacesset pathFile to quoted form of pathFile
end tell
Copy the code
Then jump to the specified directory via the AppleScript API provided by iTerm:
ell application "Finder"
set pathFile to selection as text
setPathFile to get POSIX path of pathFile -- Prevents directories from jumping if there are Spacesset pathFile to quoted form of pathFile
set pathFile to "cd " & pathFile
--set the clipboard to pathFile
tell application "iTerm"
create window with default profile
tell current session of current window
write text pathFile
end tell
end tell
end tell
Copy the code
Once we’re done with the script, Alfred can configure a Hotkey to execute the script quickly:
The Hotkey I have configured is com + T, so if I press com + T, it will open iTerm in PWD’s directory in the current Finder window.
Shorthand solution
In every weekly meeting, in the weekly review session, I always desperately review what I did this week, especially when I share the highlights and weaknesses, all kinds of words. Here is a very effective method, is to write a daily, weekly will not tangle. Actually this method is known to all, everyone is just too lazy to remember, or did not find a good tool, I have been with impression notes for a period of time, but after a period of time, found that when the brain flashes suddenly, have a good idea and want to record down, yet impression notes is not open, then you too lazy to open to record again. To avoid this happening again, I implement a shorthand workflow via Notes + Applescript + Alfred:
on alfred_script(q)
tell application "Notes"
tell account "iCloud"
tell (current date) to get (its year as integer) & "-" & (its month as integer) & "-" & day
set dataText to the result as text
set mailTitle to dataText & "- shorthand"
make new note at folder "PANote" with properties {name:mailTitle, body:q}
end tell
end tell
end alfred_script
Copy the code
Alfred gets the content and saves it in the PANote file. Now that we’ve implemented quick recording, we need to do quick lookups, again via Applescript + Alfred:
use framework "Foundation"
property NSRegularExpressionSearch : a reference to 1024
property NSString : a reference to current application's NSString
property NSJSONSerialization : a reference to current application's NSJSONSerialization
property NSUTF8StringEncoding : a reference to current application's NSUTF8StringEncoding on run argv set output to {} tell application "Notes" set folderNames to name of folders in default account repeat with folderIndex from 1 to number of folders in default account set folderName to item folderIndex of folderNames if folderName is "PANote" then set currentFolder to (a reference to item folderIndex of folders in default account) set noteIDs to id of notes of currentFolder set noteNames to name of notes of currentFolder set noteBodies to body of notes of currentFolder repeat with i from 1 to count of noteIDs set noteBody to (NSString's stringWithString:(item i of noteBodies))
set noteBody to (noteBody's stringByReplacingOccurrencesOfString:"<[^>]*>|
" withString:" " options:NSRegularExpressionSearch range:{0, noteBody's |length|()})
set noteBody to (noteBody's stringByReplacingOccurrencesOfString:"^ +| +$| +(? = )|" withString:"" options:NSRegularExpressionSearch range:{0, noteBody's |length|()}) as text
set match to (item i of noteNames) & "" & folderName & "" & noteBody
if length of noteBody is less than 100 then
set subtitle to noteBody
else
set subtitle to text 1 thru 100 of noteBody
end if
set subtitle to folderName & "|" & subtitle
set end of output to {title:(item i of noteNames), arg:(item i of noteIDs), subtitle:subtitle, match:match, uid:(item i of noteNames)}
end repeat
end if
end repeat
end tell
set output to {|items|:output}
set output to NSJSONSerialization's dataWithJSONObject:output options:0 |error|:(missing value) set output to (NSString's alloc()'s initWithData:output encoding:NSUTF8StringEncoding) as text return output end runCopy the code
The code here looks very large, but actually the principle is very simple. First, traverse all folders under the default Account, then find the PANote folder, format the found content and pass it to output. Alfred will help us display the output in a list. When we select the content in the display, we also need to open the corresponding content in Notes, so we will implement another script to open Notes:
on alfred_script(q)
tell application "Notes"
show note id q
end tell
end alfred_script
Copy the code
Note that the method ID parameter is taken from the previous code:
output to {title:xxxx, arg:xxxx, subtitle:xxxx, match:xxxx, uid:xxxx}
Copy the code
This is the format defined by Alfred. We don’t care how it is implemented, just pass the parameter according to Alfred’s specification.
Automatically pull code and compile
Every morning when I arrived at the company, the first is to wash a cup of water, and then pull the code to compile, then wait for long compile time, day after day, rain or shine ~ ~ but at the moment a daze, suddenly had an idea, why not let the system before I go to the company code compilation, I work to the company can directly, without waiting for a long build process.
We split the task step by step. First, we pull the code. Before pulling the code, we need to check whether the warehouse is clean, and then silently write the following script:
checkGitWorkspaceClean() {
echo "Action - checkGitWorkspaceClean"
if [ $# -lt1];then
echo "One param is required - the check dir.";
exit 1;
fi
if[!-d The $1 ]; then
echo "The dir does not exist - The $1";
exit 1;
fi
currentDir=`pwd`
cd The $1
result=`git status -s`
if [ -n "$result" ]; then
echo "The git workspace is not clean - The $1"
exit 1
fi
cd $currentDir
}
Copy the code
Git status -s command is used to check whether the current repository is in pull code state. If not, exit directly.
The next step is to pull the latest code for all current branches. We need to get the branch name and pull the latest code for that branch:
pullLatestCode() {
echo "Action - pullLatestCode"
if [ $# -lt1];then
echo "One param is required - the check dir.";
exit 1;
fi
if[!-d The $1 ]; then
echo "The dir does not exist - The $1";
exit 1;
fi
currentDir=`pwd`
cd The $1
currentBranch=`git branch | grep "*"`
currentBranch=${currentBranch/* /}
`git pull git pull --rebase origin ${currentBranch}`
cd $currentDir
}
Copy the code
If you feel familiar with this code, it is actually introduced in the shell section, but this is just to apply the above content to the actual scenario.
After pulling the code, we can compile the code through XcodeBuild. The XcodeBuild parameter can be referenced in the Apple official help documentation. Here you can compile using emulator by default:
buildProject() {
echo "Action - pullLatestCode"
if [ $# -lt1];then
echo "One param is required - the check dir.";
exit 1;
fi
if[!-d The $1 ]; then
echo "The dir does not exist - The $1";
exit 1;
fi
currentDir=`pwd`
cd The $1
xcodebuild -workspace ${PARS_PROJECT_NAME}.xcworkspace -scheme ${PARS_PROJECT_NAME} -sdk iphonesimulator build
cd $currentDir
}
Copy the code
In this way, the entire pull and compile process can be implemented through the code, but before compiling the code, we should check whether there is a conflict in the warehouse, if there is a conflict, do not start compiling, so the correct process is:
checkGitWorkspaceClean $PARS_PROJECT_DIR
pullLatestCode $PARS_PROJECT_DIR
checkGitWorkspaceClean $PARS_PROJECT_DIR
buildProject $PARS_PROJECT_DIR
Copy the code
AppleScript displays visual reminders, such as pop-ups, when the compilation is not complete. These optimizations can be added at your convenience without further explanation.
If compiling on the terminal is not intuitive enough to see the compilation progress directly, we can optimize the code compilation process by calling Xcode directly to compile or run the code with AppleScript:
tell application "Xcode"
open "/Users/xxxxx/xxxx/xxxxx/xxxxx.xcworkspace"
set workspaceDocument to workspace document "xxxxx.xcworkspace"
repeat 120 times
if loaded of workspaceDocument is true then
exit repeat
end if
delay 1
end repeat
if loaded of workspaceDocument is false then
error "Xcode workspace did not finish loading within timeout."
end if
set actionResult to run workspaceDocument
repeat
if completed of actionResult is true then
exit repeat
end if
delay 1
end repeat
end tell
Copy the code
At this point, I have covered the most critical functions of pulling and compiling code. As for how to execute the timing, IT has been described in detail in the previous section and will not be repeated here. The inconvenient problem with a scheduled task is that it does not start when your computer is shut down or hibernated. It’s also not a good idea to set your computer to be on standby, because you need to take care of your property. A better idea would be to write this script as Alfred’s workflows. When we arrived at work, we could have executed the workflows for a second or two, then washed a cup of water, had breakfast, etc. By the time you clear up the mess, the code will be almost ready to compile.
brainstorm
In sharing with the team, the team came up with a better idea of when to automatically pull code and compile it: execute the script every night at 12 p.m. (when everyone else leaves work), and then sleep the computer to avoid long stand-by periods.
conclusion
This article simply shares how to use tools to deal with some of the tedious things encountered in daily work, through the use of scripts and other ways to achieve automation, so as to improve personal work efficiency. Here’s just an idea and some examples, but it’s up to you to use the tools yourself, and the more you use them, the better you’ll get.
For more content, please pay attention to my official account: