Jalankan perintah ketika sistem idle dan kapan aktif lagi

15

Saya ingin menjalankan perintah ketika pengguna menjadi tidak aktif (sistem idle). Sebagai contoh:

echo "You started to be inactive."

Juga, ketika pengguna menjadi aktif kembali (sistem tidak lagi menganggur):

echo "You started to be active, again."

Saya perlu skrip shell yang akan melakukan ini. Apakah ini mungkin tanpa timer / interval? Mungkin beberapa kejadian sistem?

Ionică Bizău
sumber
2
Bisakah Anda menjelaskan sedikit lebih dalam tentang apa yang sebenarnya ingin Anda capai?
Nils
3
Bagaimana Anda mengukur kemalasan? Apakah pengguna menonton film idle (karena dia tidak berinteraksi dengan komputer)? Apakah pengguna yang login jauh aktif?
Gilles 'SO- stop being evil'
Dari yang saya tahu, sistem memiliki konsep bawaan ini : idle , active etc. Apakah ini benar?
Ionică Bizău
@ IonicăBizău: Tidak juga. Menganggur dalam konteks sistem hanya akan berarti bahwa semua proses sedang tidur, yaitu 'menunggu sesuatu'. Meskipun ini mungkin terjadi cukup sering pada sistem modern dan bahkan mungkin terjadi sebagian besar waktu, itu tidak tetap seperti itu selama selalu ada sesuatu yang harus dilakukan dan jika itu memperbarui jam. Kemalasan , terutama dalam konteks pertanyaan Anda, lebih merupakan fungsi pengguna daripada sistem dan bahkan biasanya dikaitkan dengan sesi tertentu.
Adaephon
@Adaephon Ok. Dalam konsep saya, sistem idle ketika pengguna tidak melakukan tindakan apa pun (memindahkan mouse, klik, tekan tombol) di komputer selama x menit. Sistem menjadi aktif ketika pengguna melakukan tindakan pertama: mengklik tombol mouse, memindahkannya, menekan tombol, dan sebagainya. Apakah mungkin untuk mendeteksi status aktif idle * / * ini menggunakan skrip shell?
Ionică Bizău

Jawaban:

17

Utas ini di forum ArchLinux berisi program C pendek yang menanyakan xscreensaver untuk informasi berapa lama pengguna menganggur, ini sepertinya cukup dekat dengan kebutuhan Anda:

#include <X11/extensions/scrnsaver.h>
#include <stdio.h>

int main(void) {
    Display *dpy = XOpenDisplay(NULL);

    if (!dpy) {
        return(1);
    }

    XScreenSaverInfo *info = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
    printf("%u\n", info->idle);

      return(0);
}

Simpan ini sebagai getIdle.cdan kompilasi dengan

gcc -o getIdle getIdle.c -lXss -lX11

untuk mendapatkan file yang dapat dieksekusi getIdle. Program ini mencetak "waktu idle" (pengguna tidak bergerak / mengklik dengan mouse, tidak menggunakan keyboard) dalam milidetik, sehingga skrip bash yang dibangun berdasarkan ini bisa terlihat seperti ini:

#!/bin/bash

idle=false
idleAfter=3000     # consider idle after 3000 ms

while true; do
  idleTimeMillis=$(./getIdle)
  echo $idleTimeMillis  # just for debug purposes.
  if [[ $idle = false && $idleTimeMillis -gt $idleAfter ]] ; then
    echo "start idle"   # or whatever command(s) you want to run...
    idle=true
  fi

  if [[ $idle = true && $idleTimeMillis -lt $idleAfter ]] ; then
    echo "end idle"     # same here.
    idle=false
  fi
  sleep 1      # polling interval

done

Ini masih membutuhkan jajak pendapat rutin, tetapi melakukan semua yang Anda butuhkan ...

Jasper
sumber
Bekerja sebagaimana mestinya! +1
Ionică Bizău
Anda layak mendapat lebih banyak poin!
Ionică Bizău
2
Anda dapat menyimpan sendiri kompilasi program Anda sendiri dan hanya menggunakan xprintidle, yang tersedia di sebagian besar distribusi dan melakukan hal yang persis sama.
Kerusuhan
3

TMOUT dalam bash akan mengakhiri sesi interaktif setelah jumlah detik yang ditentukan. Anda dapat menggunakan mekanisme itu.

Anda dapat menangkap logout dengan mengatur jebakan yang sesuai (saya tidak mengujinya), atau dengan menggunakan skrip bash-logout (~ / .bash_logout).

Berikut adalah jawaban pengguna super yang baik ke arah itu.

Nils
sumber
Ini tidak membahas bagaimana pengguna akan menjalankan perintah, daripada keluar, setelah $TMOUTdetik berlalu.
chepner
Bisakah Anda menambahkan lebih banyak informasi ke jawaban Anda? Masih belum jelas bagi saya ...
Ionică Bizău
@ chepner Saya menambahkan beberapa detail pada jawaban saya.
Nils
Either way, ini hanya mengeluarkan pengguna setelah waktu habis. Saya tidak berpikir ada cara untuk membatalkan logout, baik dari EXITjebakan atau dari .bash_logout.
chepner
3

Ini bukan apa yang Anda minta, tetapi selalu ada batchperintah-(biasanya doa khusus- atperintah dan menggunakan atd-daemon).

batchmemungkinkan Anda mengeluarkan perintah untuk dijalankan ketika rata-rata beban turun di bawah batas tertentu (biasanya 1,5, tetapi ini dapat diatur saat memulai atd). Dengan atitu juga mungkin untuk memberi isyarat pekerjaan sedemikian rupa sehingga bukannya dijalankan pada waktu tertentu; pekerjaan baru dikirim pada batchsaat itu, dan pertama kali dijalankan ketika rata-rata beban turun (mis. itu berjalan segera setelah rata-rata beban turun di bawah 1,5 kadang-kadang setelah pukul 02:00).

Sayangnya, batch-job akan berjalan ke akhir, tidak akan berhenti jika komputer tidak lagi menganggur.

+++

Jika Anda harus mengikuti rute pemrograman (yang terlihat dari jawaban lain), saya pikir saya akan mencoba membuat sesuatu yang mirip dengan atdatau cronddaemon, yang memantau pengguna yang masuk dan / atau memuat rata-rata. Daemon ini kemudian dapat menjalankan skrip / program dari direktori tertentu, dan memulai / melanjutkan atau menghentikannya (dengan sinyal) sesuai kebutuhan.

Baard Kopperud
sumber
Jika Anda melakukan ini dan menggunakan .lockfile Anda dapat dengan mudah menangani masalah waktu.
mikeserv
2

Utas ini memiliki beberapa solusi berdasarkan mendeteksi aktivitas keyboard dan mouse. Saya lari xprintidledari pekerjaan cron yang dimulai setiap beberapa menit. Tetapi karena mereka menunjukkan xprintidletidak terawat, jadi Anda mungkin ingin menginstal modul Perl dan menggunakannya:

$ cpanm X11::IdleTime
...
$ sleep 10; perl -MX11::IdleTime -le 'print GetIdleTime()'
9

Saya akan menggunakan salah satu solusi dengan polling dari cron, dalam skrip yang keluar di bagian atas jika UI belum cukup menganggur. Tentu saja skrip akan membutuhkan export DISPLAY=:0.0untuk berbicara dengan X11.

Ingatlah bahwa keyboard dan mouse Anda mungkin tidak aktif saat menonton film, atau menjalankan tugas yang berat CPU.

Metamorf
sumber
1

Saya tidak tahu cara untuk melakukan ini tanpa polling semacam statistik sistem, seperti jawaban lain menggunakan screensaver atau penghitung waktu bash, atau menjalankan dari .bash_logout, tapi di sini ada ide untuk memeriksa penggunaan CPU.

Ini masih akan melibatkan pemungutan suara setiap n detik, dan jika penggunaan CPU Anda di bawah jumlah apa pun yang Anda pilih maka Anda dapat skrip apa pun yang ingin Anda jalankan. Namun, apa pun yang Anda jalankan dapat meningkatkan penggunaan CPU, tetapi Anda bisa menggunakan "barang" Anda dengan baik untuk tidak menghitungnya.

Berikut ini skrip pengujian menggunakan top, tetapi Anda dapat menggunakan mpstat saja, atau periksa rata-rata pemuatan?

while true
do
idle=$(top -bn2 | grep "Cpu(s)"|tail -n 1|sed "s/.*, *\([0-9.]*\)%* id.*/\1/")
echo "idle is $idle"
if [[ $idle > 90 ]]
then
    echo "idle above 90%"
    echo "Do stuff now"
else
    echo "idle below 90%"
    echo "Stop doing stuff now"
fi
sleep 1
done

Itu hanya naskah yang saya lempar bersama untuk menguji membaca idle dari atas. Anda dapat menguraikan /proc/stattetapi saya pikir ini hanya menunjukkan waktu total, dan Anda harus membandingkan hasilnya dalam suatu interval. Top memiliki masalah sendiri untuk saya (linux mint 16), pada menjalankan pertama tampaknya tidak pernah mengubah cpustats, seolah-olah harus menunggu untuk menguraikan / proc / stat itu sendiri, maka top -bn2secara teori tetapi secara teori top -bn1harus bekerja.

Xen2050
sumber
Ugh ... benarkah? Polling statistik CPU?
Rolf
Omong-omong, Anda juga bisa polling wperintah yang menunjukkan waktu idle pengguna. - Ngomong-ngomong aku tidak menghakimi, hanya saja bagiku, aku ingin mendeteksi idle untuk mematikan mesin, menghemat daya, dan pemungutan suara menentangnya.
Rolf
@Rolf Kedengarannya cukup menghakimi ... karena komentar itu benar-benar tidak banyak menambahkannya mungkin harus dihapus, ya? Bagaimanapun, jawaban lain menggunakan waktu idle dalam beberapa cara berbeda, tetapi bagaimana Anda bisa mendeteksi idle tanpa melihat / bertanya pada sistem?
Xen2050