2014年01月05日
Remote notifications
This post explains how to get notifications (libnotify) from a remote system. Typically this is useful with an IRC client accessible through SSH.
Prerequisites:
On the client, modify the SSH configuration to introduce two elements:
Example entry for ~/.ssh/config:
socat is used to bind a port on the local system, it will take the notifcation messages, and write them to the executed shell script notify-remote.sh.
The shell script will then simply call notify-send to display a notification with the default notification daemon.
notify-remote.sh:
Now it is possible to connect to the remote host and "write" notifications:
Copy the irssi script available bellow to get notifications from hilights, and private messages.
Once the script is copied, execute /script load rnotify.pl inside irssi.
~/.irssi/scripts/autorun/rnotify.pl:
Prerequisites:
- A notification daemon! (dunst, xfce4-notifyd, etc.)
- socat
- notify-send
apt-get install socat libnotify-bin
On the client, modify the SSH configuration to introduce two elements:
- forward a TCP port,
- execute a local command.
Example entry for ~/.ssh/config:
Host remote-host Hostname remote-host.gandi.net RemoteForward 12000 localhost:12000 PermitLocalCommand yes LocalCommand socat -u tcp4-listen:12000,reuseaddr,fork,bind=127.0.0.1 exec:$HOME/.local/bin/notify-remote.sh 2>/dev/null &The fowarded TCP port will be used to netcat notification messages to the local system.
socat is used to bind a port on the local system, it will take the notifcation messages, and write them to the executed shell script notify-remote.sh.
The shell script will then simply call notify-send to display a notification with the default notification daemon.
notify-remote.sh:
#!/bin/sh delay="5000" read line summary="$line" read line msg="$line" read line if [ "$line" = "" ] && [ "$summary" != "" ]; then [ -x "$(which notify-send)" ] && notify-send -u critical -t "$delay" -- "$summary" "$msg" fi
Now it is possible to connect to the remote host and "write" notifications:
local$ ssh remote-host remote-host$ echo -e 'Summary\nBody\n\n' | nc 127.0.0.1 12000
Integrate into irssi
Copy the irssi script available bellow to get notifications from hilights, and private messages.
Once the script is copied, execute /script load rnotify.pl inside irssi.
~/.irssi/scripts/autorun/rnotify.pl:
# shamelessly copied from http://git.esaurito.net/?p=godog/bin.git;a=blob;f=rnotify.pl use strict; use Irssi; use HTML::Entities; use vars qw($VERSION %IRSSI); $VERSION = "0.01"; %IRSSI = ( authors => 'Luke Macken, Paul W. Frields', contact => 'lewk@csh.rit.edu, stickster@gmail.com', name => 'rnotify', description => 'Use libnotify to alert user to hilighted messages', license => 'GNU General Public License', url => 'http://lewk.org/log/code/irssi-notify', ); Irssi::settings_add_str('misc', $IRSSI{'name'} . '_port', '12000'); Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_if_away', 0); sub is_port_owner { my ($port, $uid) = @_; my $wanted = sprintf("0100007F:%04X", $port); # XXX linux-specific open HANDLE, "< /proc/net/tcp" || return 0; while(<HANDLE>){ # sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode my @splitted = split /\s+/; my $local = $splitted[2]; my $remote = $splitted[3]; my $uid = $splitted[8]; return 1 if $local eq $wanted and $uid == $<; } close HANDLE; return 0; } sub notify { my ($server, $summary, $message) = @_; $message = HTML::Entities::encode($message); $summary = HTML::Entities::encode($summary); # echo \ escaping $message =~ s/\\/\\\\/g; $summary =~ s/\\/\\\\/g; my $port = Irssi::settings_get_str($IRSSI{'name'} . '_port'); return if ! is_port_owner($port, $<); # check for being away in every server? return if $server->{usermode_away} && (Irssi::settings_get_bool($IRSSI{'name'} . '_if_away') == 0); # XXX test for other means of doing TCP #print("echo '$summary\n$message\n\n' | /bin/nc 127.0.0.1 $port"); system("echo '$summary\n$message\n\n' | /bin/nc 127.0.0.1 $port &"); #my $pid = open(FH, "|-"); #if( $pid ){ # print FH "$summary\n$message\n\n"; # close(FH) || warn "exited $?"; #}else{ # exec("/bin/nc 127.0.0.1 $port") || warn "can't exec $!"; #} } sub print_text_notify { my ($dest, $text, $stripped) = @_; my $server = $dest->{server}; return if (!$server || !($dest->{level} & MSGLEVEL_HILIGHT)); my $sender = $stripped; $sender =~ s/^\<.([^\>]+)\>.+/1円/ ; $stripped =~ s/^\<.[^\>]+\>.// ; my $summary = "Message on $dest->{target}"; notify($server, $summary, $stripped); } sub message_private_notify { my ($server, $msg, $nick, $address) = @_; return if (!$server); notify($server, "Private message from ".$nick, $msg); } sub dcc_request_notify { my ($dcc, $sendaddr) = @_; my $server = $dcc->{server}; return if (!$dcc); notify($server, "DCC ".$dcc->{type}." request", $dcc->{nick}); } Irssi::signal_add('print text', 'print_text_notify'); Irssi::signal_add('message private', 'message_private_notify'); Irssi::signal_add('dcc request', 'dcc_request_notify'); # vim: et
2013年08月15日
rndc retransfer failed: not found
I came accross the dummy error rndc: 'retranfer' failed: not found, with many unhelpful articles. If you run a rndc retranfer command, and get this error, make sure there is an entry for the zone on the slave, it may be helpful…
2013年07月02日
Reorder network devices set by udev
In order to reorder network devices (e.g. swap eth1 with eth2), the persistent-net rules from udev can be edited. Usually there is a file at the following location:
/etc/udev/rules.d/70-persistent-net.rulesThe file contains several rules, for example:
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="3c:ab:cd:00:ab:cd", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2" SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="3c:ab:cd:00:ab:ce", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"By editing this file it is possible to change the NAME of each rule. After that, to reload the rules, simply issue this command:
udevadm control --reload-rulesEdit: you need to unload the modules first (modprobe -r e1000e for example), ensure the udev rules are reloaded, and load the modules back in. If the network drivers are built into the kernel, you need to reboot.
2013年05月18日
Making use of custom actions with Xfce Appfinder
One addition in the latest versions of Appfinder was the custom actions. I never used it until after I started typing several times twitter which didn't work (a habit from the web browser url bar).
The custom actions can be useful for anything, and it's really quick to run it.
Examples of custom actions:
The custom actions can be useful for anything, and it's really quick to run it.
Examples of custom actions:
- twitter: xdg-open https://twitter.com/
- us: setxkbmap us
2013年03月14日
Moving from Unique to GtkApplication
A new class has been introduced in GTK+3 that is GtkApplication, and GApplication with GIO 2.28. A common use case is to have a single window present every time the same application or command line is run, that is also known as process uniqueness. This is already possible with Unique that was especially developed for single instance applications. This very basic post will show an example in C with Unique, and also how to do it with GtkApplication, where you will see that GtkApplication makes things even easier.
First of all, the documentation available from the GIO source code doesn't give a concrete example for process uniqueness with GApplication. There are mainly examples about using GApplication with GSimpleAction, that is pretty cool since it lets you easily define actions to run on the primary instance outside of the process, either with the same program or a different one.
First of all, the documentation available from the GIO source code doesn't give a concrete example for process uniqueness with GApplication. There are mainly examples about using GApplication with GSimpleAction, that is pretty cool since it lets you easily define actions to run on the primary instance outside of the process, either with the same program or a different one.
Single window with Unique
In the following example, a UniqueApp class is instantiated, then it's checked against another running instance. If not, a window is created and a handle is connected to the UniqueApp object to react on received messages. Otherwise a message is sent, and the existing instance will execute the connected handle and put the window in front.#include <unique/unique.h> #include <gtk/gtk.h> static UniqueResponse cb_unique_app (UniqueApp *app, gint command, UniqueMessageData *message_data, guint time_, gpointer user_data) { GtkWidget *window = user_data; if (command != UNIQUE_ACTIVATE) { return UNIQUE_RESPONSE_PASSTHROUGH; } gtk_window_present (GTK_WINDOW (window)); return UNIQUE_RESPONSE_OK; } gint main (gint argc, gchar *argv[]) { GtkWidget *window; UniqueApp *app; gtk_init (&argc, &argv); app = unique_app_new ("info.mmassonnet.UniqueExample", NULL); if (unique_app_is_running (app)) { if (unique_app_send_message (app, UNIQUE_ACTIVATE, NULL) == UNIQUE_RESPONSE_OK) { g_object_unref (app); return 0; } } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_show (window); gtk_main (); return 0; }
Single window with GtkApplication
In this example, a GtkApplication class is instantiated. This one is then registered, and a check is done to know if the running process is the primary one or a remote one. Just like in the previous example, either the process is the main one and a window is created and shown, otherwise a signal is sent and the connected handle will put the window in front. The handle used here is directly a GTK function that presents the window which spares the need to write a custom handler.#include <gtk/gtk.h> gint main (gint argc, gchar *argv[]) { GtkWidget *window; GtkApplication *app; GError *error = NULL; gtk_init (&argc, &argv); app = gtk_application_new ("info.mmassonnet.GtkExample", 0); g_application_register (G_APPLICATION (app), NULL, &error); if (error != NULL) { g_warning ("Unable to register GApplication: %s", error->message); g_error_free (error); error = NULL; } if (g_application_get_is_remote (G_APPLICATION (app))) { g_application_activate (G_APPLICATION (app)); g_object_unref (app); return 0; } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_show (window); g_signal_connect_swapped (app, "activate", G_CALLBACK (gtk_window_present), dialog); gtk_main (); return 0; }In both examples there is just one difference, it is how the primary process is seen. With Unique there is a function to know if another instance is running, while with GtkApplication there is a function to know if the current process is not the primary one e.g. a remote instance. I prefer the second approach, since with Unique if there is only one instance running, the is_running property will tell you false but the primary instance is running, isn't it? But anyhow, as you can see, it is possible to implement painlessly what is done by Unique with GtkApplication.
2012年12月23日
Apache restart with Vim autocmd
In order to execute a command right after saving a file in Vim, you can use the :autocmd command. Here is a quick example how it can be useful with Apache files.
NB: on my system, Debian in this case, an Apache file is automatically recognized as filetype=apache.
NB: on my system, Debian in this case, an Apache file is automatically recognized as filetype=apache.
augroup apache autocmd BufWritePost */sites-enabled/* !/etc/init.d/apache2 restart augroup END
Subscribe to:
Comments (Atom)