My old shell scripts that have been retired from my dotfiles.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
4.2 KiB

  1. #!/usr/bin/perl -w
  2. # screenspy - Linux desktop monitoring daemon. Must be run as root.
  3. # This script monitors one or more hardware devices (usually under /dev) for
  4. # Linux systems running an X window manager.
  5. #
  6. # This script must be run as root because usually only root can read from
  7. # hardware devices directly. You can set up a panel launcher to run this
  8. # script with `sudo` if you previously set up the sudoers file to let your
  9. # user run this script with no password.
  10. #
  11. # --Kirsle
  12. # http://sh.kirsle.net/
  13. use strict;
  14. use warnings;
  15. use threads;
  16. use threads::shared;
  17. #################
  18. # Configuration #
  19. #################
  20. # X display to grab screenshots from.
  21. $ENV{DISPLAY} ||= ":0.0";
  22. # Devices to monitor.
  23. our @devices = (
  24. "/dev/console", # keyboard input
  25. "/dev/input/mice", # mouse input
  26. );
  27. # Screenshot command.
  28. our $screenshot = 'scrot -q 85 "%s"';
  29. # Output directory for screenshots.
  30. our $outdir = '/home/kirsle/Pictures/screenspy';
  31. # Calibration: number of seconds (after no activity) for it to take a screenshot.
  32. our $threshold = 2; # I found that 2 seconds is the best for my system, 1 second and it takes screenshots too often.
  33. # Calibration: if there's too much activity after the threshold, take screenshots every N seconds.
  34. our $prolonged = 5;
  35. # If you want some indication that the app is running, put the command to run in here.
  36. # This command will be repeatedly run. Recommended is to use zenity and put an icon in
  37. # your system tray. Leave blank for no command.
  38. our $notify = "zenity --notification --window-icon=/usr/share/pixmaps/gnome-spider.png --text 'Running...'";
  39. #####################
  40. # End Configuration #
  41. #####################
  42. # Only let this script run once.
  43. &checkdupes();
  44. # Each thread will report the time when the last event happened.
  45. my %lastEvent : shared;
  46. my %changed : shared;
  47. # Spawn a thread for each device.
  48. my @threads = ();
  49. foreach my $dev (@devices) {
  50. # Make sure we can read the device.
  51. if (!-r $dev) {
  52. system("zenity --error --text \"Don't have permission to read from device $dev\"");
  53. }
  54. push (@threads, threads->create (\&monitor, $dev));
  55. }
  56. # If they want a command run, spawn a thread for it too.
  57. if (length $notify) {
  58. push (@threads, threads->create (\&notify));
  59. }
  60. # Loop forever and let the threads do their thing.
  61. while (1) {
  62. # See if any events have stopped for longer than the threshold.
  63. foreach my $dev (keys %lastEvent) {
  64. if ($lastEvent{$dev} > 0 && time() - $lastEvent{$dev} >= $threshold) {
  65. # take screenshot
  66. print "$dev: idle, taking screenshot (" . (time() - $lastEvent{$dev}) . "; $threshold)\n";
  67. &screenshot();
  68. $lastEvent{$dev} = 0;
  69. $changed{$dev} = 0;
  70. }
  71. }
  72. select(undef,undef,undef,0.01);
  73. }
  74. sub monitor {
  75. my $device = shift;
  76. print "Monitoring device: $device\n";
  77. # Store the time when the last event was seen.
  78. $lastEvent{$device} = 0;
  79. # When the lastEvent is first set (away from 0), record the time it was changed.
  80. # This way for prolonged activity we can still take screenshots.
  81. $changed{$device} = 0;
  82. open (READ, $device);
  83. my $buffer;
  84. while (read(READ, $buffer, 1)) {
  85. # Store the last event time
  86. if ($lastEvent{$device} == 0) {
  87. $changed{$device} = time();
  88. }
  89. $lastEvent{$device} = time();
  90. # Too much activity?
  91. if ($changed{$device} > 0 && time() - $changed{$device} > $prolonged) {
  92. # Take screenshot.
  93. print "$device: prolonged activity (> $prolonged seconds)\n";
  94. &screenshot();
  95. $changed{$device} = time();
  96. }
  97. }
  98. close (READ);
  99. }
  100. sub notify {
  101. while (1) {
  102. system($notify);
  103. }
  104. }
  105. sub screenshot {
  106. print "Taking screenshot!\n";
  107. my @time = localtime(time());
  108. my $date = join(" ",
  109. join("-",
  110. sprintf("%04d", $time[5] + 1900),
  111. sprintf("%02d", $time[4] + 1),
  112. sprintf("%02d", $time[3]),
  113. ),
  114. join(":",
  115. sprintf("%02d", $time[2]),
  116. sprintf("%02d", $time[1]),
  117. sprintf("%02d", $time[0]),
  118. ),
  119. );
  120. my $fname = $date;
  121. my $i = 1;
  122. while (-f "$outdir/$fname.png") {
  123. $fname = $date . " [$i]";
  124. $i++;
  125. }
  126. my $cmd = $screenshot;
  127. $cmd =~ s/%s/$outdir\/$fname\.png/ig;
  128. system($cmd);
  129. }
  130. sub checkdupes {
  131. my $ps = `ps aux | grep screenspy`;
  132. foreach my $line (split(/\n/,$ps)) {
  133. chomp $line;
  134. next if $line =~ /grep/i;
  135. next if $line =~ /$$/i;
  136. if ($line) {
  137. die "Script is already running!\n";
  138. }
  139. }
  140. }