如何从AppleScript或Shell脚本触发通知中心通知?


305

我希望能够利用AppleScripts和我编写的Shell脚本中的10.8的通知中心功能。

我可以从AppleScript或Shell脚本中使用内置命令或第三方库吗?

理想情况下,可以控制通知的类型和图标,但即使只是触发带有股票图标(但自定义文本)的基本横幅的功能也将受到赞赏。


Answers:


428

使用Mavericks及更高版本,您可以使用AppleScript的“显示通知”来执行此操作:

display notification "Lorem ipsum dolor sit amet" with title "Title"

                          

就是这样-实际上就是这么简单!没有3 三方库或应用程序所需的,是在其他系统上使用完全可移植。顶部是10.9通知,中间是10.10 DP,底部是10.10。

可以使用/ usr / bin / osascript从外壳运行AppleScript:

osascript -e 'display notification "Lorem ipsum dolor sit amet" with title "Title"'

您还可以通过添加…来进一步自定义警报。

  • 字幕

    附加“字幕”,后跟包含字幕的字符串或变量。

    display notification "message" with title "title" subtitle "subtitle"

    上面的示例产生以下通知:

  • 声音

    附加“声音名称”,后跟将与通知一起播放的声音名称。

    display notification "message" sound name "Sound Name"

    有效的声音名称是位于…中的声音的名称。

    • ~/Library/Sounds
    • /System/Library/Sounds

可以将发布通知包装为命令行脚本。以下代码可以在Terminal中运行,并将在/ usr / local / bin(必须存在,添加到$ PATH)中添加脚本notify

cd /usr/local/bin && echo -e "#!/bin/bash\n/usr/bin/osascript -e \"display notification \\\"\$*\\\"\"" > notify && chmod +x notify;cd -

这是上面将添加以通知的脚本。

#!/bin/bash
/usr/bin/osascript -e "display notification \"$*\""

现在显示通知:

notify Lorem ipsum dolor sit amet
sleep 5; notify Slow command finished

9
@ceilingcat这是AppleScript。要在Terminal中运行它,请使用osascript(请参阅答案)。
grg

8
唯一的问题display notification是,当您单击它时,将显示打开文件对话框。
ɹoƃı

7
是否可以使通知弹出窗口永久存在(N秒后不自动隐藏),直到用户明确单击为止。
Sridhar Ratnakumar

25
女士们,先生们,在经过一个小时的互联网调查之后,我发现了如何让通知窗口一直停留到被用户拒绝!它实际上是由“系统偏好设置”中的设置控制的,而不是由编写的脚本中的某些参数控制的。这两个图像应该解释这一切i.imgur.com/cNOqFyX.jpg i.imgur.com/i8oyoan.jpg有乐趣的家伙,感谢@grgarside为伟大的答案。
Vic Jang 2015年

4
请注意,文本必须用双引号引起来。单引号无效。因此,如果您需要文本中的变量,则不能编写"display ... '$mytext' ...",但需要使用转义的双引号: "display notification \"$mytext\" ..."
mivk

93

终端通知者

从自述文件:

terminal-notifier是用于发送Mac OS X用户通知的命令行工具,该通知在Mac OS X 10.8中可用。

由于NSUserNotification无法在“基础工具”中运行,因此当前将其打包为应用程序捆绑包 。雷达:// 11956694

Kicker将使用此工具来显示由于文件系统更改而执行的命令的状态。(v3.0.0)

下载

可从下载部分获得经过预编译的二进制代码,这些代码已签名并可以使用。

用法

$ ./terminal-notifier.app/Contents/MacOS/terminal-notifier group-ID sender-name message [bundle-ID]

为了使用终端通知程序,您必须在应用程序包调用二进制文件 。

第一个参数指定通知所属的“组”。对于任何“组”,将只显示一个通知,以替换以前发布的通知。例如:发件人的进程ID,以按唯一进程对通知进行作用域;或当前工作目录,以按项目对通知进行作用域。

第二个和第三个参数描述了通知本身,分别是其“标题”和“消息”。例如,要将通知的发送方传达给用户,您可以指定发送方的名称作为标题。

第四个也是最后一个参数是可选的。它指定当用户单击通知时应激活哪个应用程序。默认情况下,这将激活Terminal.app,以启动另一个应用程序,而不是指定应用程序的包标识符。例如,要启动Safari.app,请使用:com.apple.Safari


太好了,一个很棒的图书馆!很希望看到它可以通过控制图标和警报与横幅进行更新,但是绝对有用。感谢您的链接!i.imgur.com/tsCeK.png
内森·格林斯坦

2
伟大的小应用程序,我创建了一个启动器,并将其放在/ usr / local / bin中,以便可以在终端等任何地方使用它。启动器脚本:#!/ bin / bash cd /Applications/terminal-notifier.app/Contents/ MacOS ./terminal-notifier $ *
johanandren 2012年

4
启动器很有用,如果您对其稍作更改,则可用于带引号的带空格的文本:#!/ bin / bash cd /Applications/terminal-notifier.app/Contents/MacOS ./terminal-notifier“ $ @”
Redbeard

27

我只想在@grgarside的答案中添加注释,因为我知道很多人都希望有一个通知弹出窗口,该弹出窗口只能通过单击按钮才能消除。

比较方式

我为您找到了解决方案:

它实际上是由“系统偏好设置”中的设置控制的,而不是由编写的脚本中的某些参数控制的。这两张图片应该说明了一切

感谢@grgarside的出色回答。

系统偏好


5
请注意,具体应用会有所不同。Script Editor仅用于Script Editor.apposascript。在服务工作流程中,它是Automator Runner。在里面Automator.app的时候Automator
cde

1
我感到烦恼的是,如果我单击横幅,它会显示脚本编辑器应用程序。我想为它只是点击消失,但这篇文章所指出的,你可以通过它和触控板,向右滑动,即可悬停让它悄悄离去:osxdaily.com/2012/09/05/...
约书亚·戈德堡

@JoshuaGoldberg感谢您添加!我有一天直观地发现了这一点,这是我喜欢Mac OS X的一件事,它可以按照您期望的方式工作:)
Vic Jang

22

现在,您可以使用Growl2(可从App Store获得)进行此操作。安装Growl并启用“ OS X通知”(屏幕快照)

在此处输入图片说明

另外,您将需要安装GrowlNotify,以便使用命令行工具发送Growl通知。您可以在“ 下载”页面上免费下载此工具。

现在,您可以从命令行生成Growl通知,该通知将转发到Notification Center。例如:

growlnotify -n "My App" -m "Hello world"

在此处输入图片说明

请注意,目前似乎无法更改应用程序图标。


1
好的方法,尤其是如果已经安装了咆哮声。
Besi 2012年

1
我认为您也许可以使用该--icon path/to/icon.png图标选项。
2014年

已弃用/不再维护?最新更新适用于macOS 10.9 特立独行
Seamus

15

我最近分叉了终端通知程序,以构建一个命令行工具来显示通知警报(带有操作)和回复类型警报。

我将其与Shell脚本和golang应用程序结合使用,以获取用户的交互式答案。

https://github.com/vjeantet/alerter

在此处输入图片说明


1
显然也已弃用/放弃。
Seamus

15

@grgarside解决方案很好,但是容易受到脚本注入的影响,当脚本注入例如用于显示日志文件内容或类似内容时,这可能是一个主要的安全问题。

这应该更安全:

#!/bin/bash
X="$*" /usr/bin/osascript -e 'display notification system attribute "X"'

这很有趣,但是您能描述一下这样一种情况吗:我在系统上运行的只能由用户执行的脚本容易受到脚本注入的影响?
iconoclast

1
如果显示的不是您的用户内容,那么您很容易受到攻击。例如,如果您在具有公共Web服务器的系统上运行此程序,或者当某些应用程序记录了它从您读取和显示的网络中获取的字符串时,例如浏览器,邮件程序或Twitter客户端。它可以有一个“以结束字符串和语句,然后有代码,然后重新启动字符串。”
Archimedix 2015年

好的,是的。我很难想象曾经将Web表单中的内容放入我的通知中,但是您的意思是正确的。
iconoclast

1
好吧,也许您只是想说些类似的话I have a "laser"而无需通过“引用”您的“单词”来告诉您语法错误。通过转义,您可以:script 'I have a "laser"'
Archimedix

1
赞成,因为始终牢记安全性总是一件好事。有人可以复制粘贴解决方案,并以发布解决方案的人未曾考虑过的方式使用它们。
爱德华·福尔克

13

由于Growl不是免费的,并且在10.8之前的系统上没有terminal-notifier,因此我倾向于使用cocoaDialog。它是免费和开源的,因此您可能还可以随脚本一起分发。

如果您不需要太多自定义,则还可以使用AppleScript display notification,也可以像其他人已经提到的那样从外壳中调用。

但是请注意,AppleScript似乎需要双引号。因此,如果您需要变量,则将无法使用

osascript -e "display notification '$text' with title '$title'" #WRONG

您将必须使用转义的双引号。这很难看,但可以

osascript -e "display notification \"$text\" with title \"$title\""

这也适用:osascript -e 'display notification "Lorem ipsum dolor sit amet" with title "Title"'
MikeSchinkel '17

也已弃用。链接产生“此处没有GitHub Pages站点。”
Seamus

11

(这是基于@grgarside的出色答案的替代实现。)

可以osascript在shebang行中直接解释AppleScript 。

#!/usr/bin/osascript

on run argv
    if length of argv = 1 then
        display notification (item 1 of argv) with title "Notification"
    else if length of argv > 1 then
        display notification (item 1 of argv) with title (item 2 of argv)
    else
        return "<message> is required\nUsage: notify <message> [<title>]"
    end if
end run

将其保存notify在路径中的某个位置,例如/usr/local/bin/notify,并使其可执行(chmod +x notify)。它接受一条消息和一个可选的标题。如果任何一个都有空格,请将其括在引号中,以便外壳程序将其解释为单个参数。

$ notify "Lorem ipsum dolor sit amet" "Testing Notifications"

这避免了其他所有答案都容易受到的注入式攻击
Neil Mayhew

7

这是我在OS X上的ruby脚本中使用的一个很酷的脚本(以便即使从窗口切换后也可以启动脚本并获得更新):

cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'|
system ( cmd )

2
哇...所以链就像用户-> Ruby-> Shell-> AppleScript-> Objective-C-> Assembly-> CPU?
iconoclast

5

替代:

.bash_profile

function _sys_notify() {
    local notification_command="display notification \"$2\" with title \"$1\""
    osascript -e "$notification_command"
}
alias sys-notify="_sys_notify $1 $2"

使用命令: sys-notify "title" "message"


5

官方文件

https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html

如果文档被移动或删除,请在此处复制文本。

要显示通知,请向display notification命令提供要显示的字符串。(可选)提供带有标题,字幕和声音名称参数的值,以在出现通知时提供其他信息和声音警报

display notification "All graphics have been converted." with title "My Graphic Processing Script" subtitle "Processing is complete." sound name "Frog"

注意

使用脚本显示通知后,该脚本或脚本编辑器(如果脚本是从脚本编辑器中运行的)将添加到“系统偏好设置”>“通知”中的通知应用程序列表中。您可以在此处配置选项,例如将通知显示为警报还是横幅。

单击警报样式的通知中的“显示”按钮可打开显示通知的应用程序。对于脚本应用程序,再次打开应用程序的操作将触发脚本的运行处理程序,从而可能导致脚本第二次开始处理。请记住这一点,并在适当的情况下将代码添加到脚本中以处理这种情况。


1

谢谢,这正是我某些用户脚本所需要的。我做了些微修改以添加字幕和声音。如果未提供值,则将其忽略。

function _sys_notify() {
local notification_command="display notification \"$2\" with title \"$1\" subtitle \"$3\" sound name \"$4\""
osascript -e "$notification_command"
}

alias sys-notify="_sys_notify $1 $2 $3 $4"

对于声音,请使用不带/ System / Library / Sounds扩展名的声音文件名。例如,要使用文件Ping.aiff,请使用$ 4的Ping

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.