Is there a MacOS equivalent to wall?

I'm looking for the Mac equivalent to the [U|Li]nix 'wall' (write all) command. MacOS does have a 'wall', but that apparently only writes to terminals, nothing show on logged in user GUI. I have a service task that could initiate a reboot and would like to notify the logged in user[s] of what's going on so that some dialog pops up on their screen. It need not require interaction.


Mac mini Unibody no ODD

Posted on Dec 7, 2018 8:39 PM

Reply
Question marked as Top-ranking reply

Posted on Dec 8, 2018 1:06 PM

Mark,


Here is how you slide in a notification from Python using the Python-Objective-C scripting bridge. Must be run with the System Python.


Maybe you can find a way to trigger this from some event:


#!/usr/bin/python
# Coding: UTF-8


from AppKit import NSUserNotification, NSUserNotificationCenter
import sys


def notify(title, subtitle, text):
    notification = NSUserNotification.alloc().init()
    notification.setTitle_(str(title))
    notification.setSubtitle_(str(subtitle))
    notification.setInformativeText_(str(text))
    notification.setSoundName_("NSUserNotificationDefaultSoundName")
    (NSUserNotificationCenter.defaultUserNotificationCenter().
        scheduleNotification_(notification))


def main():

    t = 'PyObjective-C Notification'
    s = 'Processing complete'
    m = 'foobar'

    notify(t, s, m)


if __name__ == '__main__':
    sys.exit(main())


Similar questions

15 replies
Question marked as Top-ranking reply

Dec 8, 2018 1:06 PM in response to markfoley

Mark,


Here is how you slide in a notification from Python using the Python-Objective-C scripting bridge. Must be run with the System Python.


Maybe you can find a way to trigger this from some event:


#!/usr/bin/python
# Coding: UTF-8


from AppKit import NSUserNotification, NSUserNotificationCenter
import sys


def notify(title, subtitle, text):
    notification = NSUserNotification.alloc().init()
    notification.setTitle_(str(title))
    notification.setSubtitle_(str(subtitle))
    notification.setInformativeText_(str(text))
    notification.setSoundName_("NSUserNotificationDefaultSoundName")
    (NSUserNotificationCenter.defaultUserNotificationCenter().
        scheduleNotification_(notification))


def main():

    t = 'PyObjective-C Notification'
    s = 'Processing complete'
    m = 'foobar'

    notify(t, s, m)


if __name__ == '__main__':
    sys.exit(main())


Dec 8, 2018 12:05 PM in response to MrHoffman

Solution for logged in user using osascript:


osascript -e 'display notification "hello world!"'


That answers the question for the logged in user running something in a [hidden] terminal or cron job (possibly, not tested), although what I'm really wanting is for a boot-launched process to be able to do this (e.g. my apcupsd program).


I'll next check the links mentioned by MrHoffman.



Dec 10, 2018 5:52 AM in response to markfoley

It sounds related to Mr. Hoffman's comment but Apple also blocked the ability for background processes to call 'CoreLocation Services' to find your Macs location.


With regards to a workaround for notifications - if needed. Have your background monitor write status to a text file somewhere. Then have a GUI tool - which could itself be faceless monitor that text file and as required display notifications. This way neither process talks directly to the other and should avoid Apple's roadblock.


For faceless script see this.


You could have this AppleScript run as a launchagent i.e. only when a user logs in. If you have it loop with a period pause it would stay running whilst the user is logged in.

Dec 10, 2018 4:11 AM in response to MrHoffman

osascript doesn't work directly in cron. I've tried several variations (could be my syntax):


50 6 * * * /bin/bash -c "/usr/bin/oascript -e 'display notification \"hello\"'"

52 6 * * * /usr/bin/oascript -e 'display notification "hello"'


But does work if cron runs a script that has osascript:


42 17 * * * /bin/bash -c "$HOME/testme"


where testme is:


#!/bin/bash

/usr/bin/osascript -e 'display notification "hello"'


That will be useful for background jobs run from the user's cron. On such job will be backing up the user's Virtual Machine, though hopefully that will be done after business hours.


Notification from root process and services is another matter. MrHoffman wrote, "GUI access from the background, ... all got yanked for misuse." Having thought about this, it makes no sense to me. If the user creates a background task that notifies the user, that's "self-misuse" at worst. Whose to care? If third-parties create background notices then a user could choose not to install annoying 3rd party software. Personally, I can't think of any circumstance which would constitute "misuse" of background notification. Quite the contrary as in my need to have the user notified if the computer is going down. Neither wall nor shutdown show a message on the GUI.


Well, I guess I'll have to investigate the suggestions you and VikingOSX have made. I'll eventually post back with my results. Perhaps you or someone could point me in the right direction for writing a "client", not sure what that means in the Mac world, and/or likewise with writing a "signed app". Possibly a tutorial or an example?

Dec 8, 2018 11:34 AM in response to markfoley

Ah. I wish you had posted that info first. Okay.


You’ve gotten your answer, then. As VikingOSX mentioned, write a client for your server-side (background) app to chat with.


Most tools trying to pop messages in notifications have to be signed. Which means you’ll either need a client running in the GUI context, and started at login. Or you’ll need a signed app. Or both.


As for the trigger, there’s a shutdown script around that can be modified. You’ve found that for the built-in UPS support, or the equivalent in the add-on apcupsd package. (The pmset command can also be used to query status, but you’ve likely found that already.)


This tool might help:

https://github.com/julienXX/terminal-notifier

https://github.com/chbrown/osx-notifier


In addition to the daemons and agents discussion mentioned earlier, the use of XPC was mentioned earlier, and that’s a common way to communicate on macOS.

https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html


Related to XPC:

https://stackoverflow.com/questions/19488241/xpc-on-mac-osx-implementation#29581061


Notification Center widget, if you want to try a slightly different approach:

https://developer.apple.com/design/human-interface-guidelines/macos/extensions/notification-center-widgets/


Power Management Events:

https://stackoverflow.com/questions/47617012/getting-shutdown-and-restart-notifications-in-macos

https://stackoverflow.com/questions/1321219/receiving-power-notifications-especially-shutdown-on-mac-osx


Dec 12, 2018 9:12 AM in response to markfoley

Well aware that wall does not solicit passwords. But if wall can access the GUI using some available means, then it's either going to have to be specially entitled to access the GUI here, or there'll need to be a more general path opened that other background tasks can use to access the GUI for legitimate purposes or for shenanigans.


If this were for eventual incorporation into a product or into some open-source package, I'd recommend using a GUI client and not a shell script and wall.

Dec 10, 2018 3:56 AM in response to markfoley

For the benefit of everyone apcupsd is a daemon provided by APC for monitoring the state of one of their APC UPS devices and (hopefully) triggering the Mac to automatically shutdown when there has been a power outage and the battery in the UPS is getting low.


If the model of UPS has a USB port it is actually possible to connect it directly to the Mac and then the Mac will monitor it automatically and display the status in System Preferences -> Energy Saver settings. No extra software is needed if you use a USB connection. However only one computer can be connected via USB. It is therefore common if you have multiple computers connected to a larger UPS to use a network connection and hence the apcupsd sofware.


Note: This might be better known as 'PowerChute'.


The Windows version of PowerChute gives you a lot more information, the Mac version is a faceless daemon like the Linux version.


There used to be a Mac third-party program from Equinux called APC Tracker that provided a lot more of a Mac experience. See here. It however has been discontinued for a long time.


There is a free alternative to apcupsd called 'NUTS' - aka Network Ups ToolS. See here. I believe this would be similar to apcupds in that it is a faceless daemon, however it supports other makes of UPS in addition to APC.


It would seem the general answer of having to write a script to monitor the status of apcupsd or NUTS and then via your script send notifications is the best approach. See this as an example.


What I would like to see is someone - logically Apple link network UPS reporting to System Preferences -> Energy Saver settings.

Dec 12, 2018 7:29 AM in response to MrHoffman

(how do you quote a reply?)

MrHoffman: "If there's no good wall (no pun intended) here, some random not-privileged app service running in the background can present—for instance—a password-grabbing prompt."


The 'wall' program doesn't solicit input, so not a security risk in the sense you are describing.


I think I've come up with a simple solution. I can use osascript from within a script like the apccontrol shutdown script (interestingly, that script looks for growl being installed). A typical notification line in this script is:


echo "Apccontrol has done: ${APCUPSD} --killpower on UPS ${2}" | ${WALL}


where $WALL is aliased to either wall or growl, if found. I've created a script, 'gwall' as follows:


#!/bin/bash


# Get optional title


if [ "$1" = "-t" ]

then

title="$2"

shift 2

else

title="from $USER"

fi


# As with 'wall', either display file or stdin


if [ -z "$1" ]

then

msg=`cat`

else

msg=`cat $1`

fi


# Get console (GUI) users and send message


who | grep console | awk '{print $1}' | \

while read usr

do

su - $usr -c "/usr/bin/osascript -e 'display notification \"${msg}\" with title \"$title\"'"

done


echo "$msg" | wall


Like 'wall', this either takes stdin or the name of a file as $1. I've added the non-wall option -t to create a title other than the default "Script Editor". It looks for console users and send the message via osascript. To finish, it sends the message via wall for users logged into a terminal. The only drawback is that this can only be executed by root since is has to 'su' to the user getting the message, but for my purposes it's all I need.


So, I'll set the WALL variable in the apccontrol script to: WALL="/usr/local/bin/gwall -t \"from apccontrol\""


Someday, I may add an arg to make the notice require user acknowledgment (display alert), and perhaps an arg to change the persistence time (defaults write com.apple.notificationcenterui bannerTime [time in seconds]).


Dec 12, 2018 1:58 PM in response to MrHoffman

This is strictly for internal, production purpose, not for a product, so I'm satisfied with what I've come up with. It permits notification to users if/when the computer goes to battery power, and if/when the computer is going down due battery exhaustion. It took a lot of research and testing on my part, but in the end uses readily available tools, no messing with new tools that would take me even longer to master.


Thanks all for your help.

Dec 12, 2018 2:38 PM in response to John Lockwood

John Lockwood: "If the model of UPS has a USB port it is actually possible to connect it directly to the Mac and then the Mac will monitor it automatically and display the status in System Preferences -> Energy Saver settings. No extra software is needed if you use a USB connection."


Although I figured out (to my satisfaction) how to get apccontrol to notify console users of power failure / shutdown, your message is intriguing. I have an APC UPS connected to this Mac via USB and I've looked at System Preferences -> Energy Saver. I see nothing there showing the status of the UPS device. It would be great if apcupsd were not needed. Can you tell me where exactly this status indicator is? Perhaps a screen-shot?

Dec 8, 2018 7:18 AM in response to markfoley

Not sure about the context of these scripts you’re working with; whether they’re associated with the logged-in user, or not.


Background activity unassociated with the logged in GUI can’t easily get to the GUI. This is a deliberate choice, and intended to keep background activities from shenanigans with the logged-in user.


Look up the daemons and agents for some background:

https://developer.apple.com/lhttps://stackoverflow.com/questions/23923017/osascript-using-bash-variable-with-a-space#23923108


You’re probably headed to push notifications or similar ugly, here.


If you’re running a shell script on behest of the logged-in GUI user, then this is much esiser and the osascript command is probably what you want.

https://stackoverflow.com/questions/23923017/osascript-using-bash-variable-with-a-space#23923108


There used to be a third-party tool here that could be helpful, Growl, unfortunately, Growl was having trouble on recent macOS releases, when last I checked. That may have gotten fixed.

http://growl.info/


Dec 8, 2018 10:14 AM in response to VikingOSX

More information: the task I'm talking about is apcupsd which starts at boot and is not associated with a user login or console. Its job is to monitor the APC battery backup device for power failure and, if the battery runs out before power is restored, to shut down the computer gracefully. I have this installed on all Linux and some Windows workstations in the office. The Linux and Mac versions have 'wall' in the notification script which works on most Linux distros, but doesn't do the job on Mac to notify logged in users on their GUI desktop. In this case "shenanigans" with the logged in user is important.


MrHoffman, I did check out Growl as part of my research and I came to the same conclusion. Their product appears to have stopped being updated after Mountain Lion.


I'll check out osascript and Distributed Objects and post back.

Dec 8, 2018 1:58 PM in response to markfoley

I’ve already mentioned osascript.


That wil only work for a process associated with the GUI session.


Your shutdown script is not.


Not unless you start the monitoring script from the login, that is. And given polling via pmset or otherwise is generally a poor approach, the power-management APIs I’ve referenced might be a better approach. In short, a client.


Write a client that does what you want.


Or write a signed app that can send notifications.


Unfortunate effort for what you want, but that’s what’s involved here.


GUI access from the background, and other analogs the old Microsoft net send command and ilk all got yanked for misuse.


Dec 10, 2018 9:24 AM in response to markfoley

Notification from root process and services is another matter. MrHoffman wrote, "GUI access from the background, ... all got yanked for misuse." Having thought about this, it makes no sense to me. If the user creates a background task that notifies the user, that's "self-misuse" at worst.


If there's no good wall (no pun intended) here, some random not-privileged app service running in the background can present—for instance—a password-grabbing prompt.


A local client could well be a Python script, AppleScript either bespoke and hand-crafted or via Automator, or whatever.


This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Is there a MacOS equivalent to wall?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.