Bagaimana cara mematikan server Linux setelah berjalan selama 60 menit?

18

Saya memiliki server yang biasanya dimatikan karena alasan keamanan. Ketika saya ingin mengerjakannya, saya mengaktifkannya, menjalankan tugas saya, dan mematikannya lagi. Tugas saya biasanya memakan waktu tidak lebih dari 15 menit. Saya ingin menerapkan mekanisme untuk mematikannya secara otomatis setelah 60 menit.

Saya telah meneliti bagaimana melakukan ini dengan cron, tapi saya rasa itu bukan cara yang tepat karena cron tidak memperhitungkan ketika server terakhir kali dihidupkan. Saya hanya bisa mengatur pola periodik, tetapi mereka tidak memperhitungkan data itu.

Bagaimana saya bisa melakukan implementasi ini?

jmhostalet
sumber
4
Lihat at(eksekusi satu kali).
dirkt
14
Saya belum melakukan ini, tetapi skrip login Anda dapat memulai sudo shutdown -h +60yang akan memulai penghitung mundur 60 menit untuk proses shutdown (-halt). Jika Anda ingin membatalkannya, Anda bisa sudo shutdown -c (ini tidak menggunakan cron)
guiverc
7
Tergantung pada sifat tugas Anda, mungkin ada baiknya menjalankannya di dalam wadah buruh pelabuhan, jadi Anda tidak perlu khawatir mematikan server. Wadah itu dibuat, itu menjalankan tugas Anda, dan itu hancur setelah itu.
Vicente Olivert Riera
6
Jangan berharap manfaat keamanan nyata dari ini. Sebagian besar kerentanan dapat dieksploitasi dalam waktu kurang dari satu detik, jadi mematikannya setelah satu jam tidak akan mencegah eksploitasi. Dan penyerang yang menemukan kerentanan dapat menunggu Anda untuk menghidupkan mesin untuk melakukan serangan.
kasperd
2
Re: @kasperd komentar, saya ulangi mengatakan bahwa Anda membutuhkan jumlah yang persis sama keamanan di server Anda terlepas dari berapa banyak atau sedikit itu sebenarnya online. Catatan, ini adalah server sehingga terhubung ke sesuatu dan itu berarti sesuatu akan tahu kapan dinyalakan - sapuan otomatis bukanlah yang Anda khawatirkan, ini koneksi apa pun dan Anda tidak dapat menghindarinya sehingga keamanan maksimum sepanjang waktu adalah satu-satunya jalan.
StephenG

Jawaban:

23

Jika Anda menjalankan tugas Anda sebagai pengguna yang sama setiap kali, Anda cukup menambahkan perintah shutdown, secara opsional dengan opsi -P, ke profil Anda. Jumlahnya adalah jumlah menit perintah shutdown tertunda. Pastikan pengguna Anda memiliki kemampuan untuk menjalankan perintah shutdown melalui sudo tanpa kata sandi.

echo "sudo shutdown -P +60" >> ~/.profile
Dirk Krijgsman
sumber
11
Waktu dalam menit, bukan detik. Coba shutdown -k -P 3600vs shutdown -k -P 60( -kmencetak pesan dinding tetapi tidak memiliki efek lain)
sebasth
12
Tetapi coba perintah ini satu kali pertama, Anda tidak ingin shutdown instan terikat ke profil Anda!
Fabian Röling
17
Saya membayangkan setiap login ssh akan menyebabkan panggilan shutdown baru. Apakah penghitung akan diatur ulang?
JoL
4
Mungkin juga bermanfaat untuk menyebutkan bahwa login tidak akan diizinkan dalam 5 menit terakhir, sebagaimana disebutkan dalam halaman shutdown.
JoL
6
Perhatikan bahwa 60 menit setelah masuk tidak sama dengan 60 menit setelah boot. Bagaimana jika Anda mem-boot mesin dan kemudian lupa login?
Hagen von Eitzen
69

Ada beberapa opsi.

  • Berikan waktu langsung ke shutdown -P:

    shutdown -P +60
    

    Perhatikan bahwa shutdown halaman manual juga menunjukkan:

    Jika argumen waktu digunakan, 5 menit sebelum sistem turun, file / run / nologin dibuat untuk memastikan bahwa login lebih lanjut tidak diperbolehkan.

  • Gunakan atperintah.

  • Buat file unit systemd atau skrip init yang berjalan shutdown -P 60saat startup.

  • Gunakan cron @rebootuntuk menjalankan perintah setelah boot.

    Tambahkan ke (root) crontab:

    @reboot shutdown -P +60
    

Untuk dua metode terakhir, Anda juga bisa menggunakan sleep 3600 && shutdown -P nowalih-alih menggunakan argumen waktu shutdownuntuk menunda shutdown selama 60 menit. Dengan cara ini login dapat dilakukan hingga saat terakhir sebelum shutdown dikeluarkan.

sebasth
sumber
2
Saya pikir dengan sleepperintah, Anda masih perlu menentukan waktu untuk shutdown- kami ingin menggunakan nowargumen itu jika kami sudah menunggu (tetapi perhatikan bahwa Anda tidak akan mendapatkan banyak peringatan untuk menyimpan pekerjaan Anda sebelum itu) menghilang dari bawah Anda!).
Toby Speight
1
Meskipun shutdown -P 60berfungsi, ini bukanlah cara bagaimana perintah harus dijalankan. Menurut halaman manual yang harus Anda gunakan shutdown -P +60. --- Juga shutdown tanpa argumen waktu (dalam contoh sleep 3600 && shutdown -P) akan ditunda satu menit (seperti shutdown -P +1). Seperti yang ditulis Toby Speight, Anda mungkin ingin menggunakannya shutdown -P now.
pabouk
34

Ini terlihat seperti masalah XY .

Tugas saya biasanya memakan waktu tidak lebih dari 15 menit. Saya ingin menerapkan mekanisme untuk mematikannya secara otomatis setelah 60 menit.

Jika Anda mematikan setelah 60 menit, Anda berisiko bahwa Anda mungkin mengalami masalah yang sangat rumit dan hanya perlu memiliki lebih banyak waktu. Banyak solusi sebelumnya tidak membuatnya mudah untuk menunda shutdown.

Jika tugas tersebut bukan tugas interaktif, melainkan tugas skrip yang dipicu secara otomatis dari komputer lain, @sdkks memberikan solusi hebat untuk itu; Anda benar-benar harus menugaskan mesin untuk menjalankan poweroff segera setelah skrip dan semua tugasnya selesai.

Namun, jika tugas Anda adalah tugas interaktif, saya sarankan untuk melakukan deteksi siaga.

Jika Anda melakukan tugas Anda dalam GUI (X11), Anda dapat mendeteksi sesi GUI idle menggunakan pendekatan yang dijelaskan di sini: Jalankan perintah ketika sistem idle dan kapan aktif lagi

Jika Anda melakukan tugas melalui terminal, Anda dapat mendeteksi pengguna yang masuk menggunakan whoperintah. Anda dapat mengatur cronjob yang mematikan mesin jika whomengembalikan hasil yang kosong. Perhatikan bahwa ini akan menjadi pendekatan yang cukup konservatif; itu tidak akan mematikan sistem jika Anda membiarkan konsol terhubung, tetapi idle.

Jika Anda ingin menjadi sedikit lebih agresif dan memutuskan sesi terminal idle juga, Anda dapat menggabungkan pendekatan sebelumnya dengan secara otomatis memutuskan sesi SSH idle ClientAliveInterval dan ClientAliveCountMax. Pendekatan lain untuk ini jika Anda tidak memiliki SSH, tetapi memiliki sesi terminal lokal, adalah dengan menggunakan waktu idle terminal seperti yang dikembalikan oleh wperintah.

Lie Ryan
sumber
2
Ini adalah poin yang sangat penting. Apa pun yang Anda laksanakan - adalah kepentingan Anda untuk memastikan bahwa Anda juga dapat membatalkan penutupan.
Bayangan
1
Ada yang salah jika masih berjalan di 60m, jadi mungkin mulai lagi. Ini bisa sangat mahal dari segi cloud. Tidak memastikan shutdown pada satu kesempatan membuat saya mengembalikan lebih dari $ 4.000.
mckenzm
8

Meskipun jawaban sebelumnya di sini semuanya memenuhi persyaratan untuk kesempurnaan, Anda juga dapat mematikan mesin segera setelah tugas selesai.

bashskrip dapat di- trapped, artinya sinyal-sinyal tertentu dapat dicegat dan tugas-tugas tertentu dapat dijalankan ketika dibutuhkan. EXITadalah salah satu sinyal yang bisa dijebak.

Anda akan dapat:

  1. Tetapkan trapuntuk EXITskrip shell otomatis Anda, yang berarti penghentian tugas otomatis Anda
  2. Set a trapfor your .bashrc EXIT, artinya kapan pun Anda keluar dari mesin itu, matikan.

Opsi # 1 akan menjadi kasus yang ideal, asalkan tugas Anda tidak memerlukan inspeksi adhoc dan penilaian manual.

Opsi # 2 akan mencakup kasing di mana Anda akan lupa untuk keluar dari terminal tanpa mematikan. Namun ada peringatan; jika Anda memiliki beberapa terminal ke mesin yang sama terbuka dan Anda keluar dari salah satunya, itu akan tetap mematikan mesin sama saja. (Dapat ditulis untuk menghindari itu, tapi saya tidak akan menyulitkan solusinya.)

cleanup(){
    # Do some tasks before terminating
    echo oh la la, cleaning is so nice
    echo "See you later, world"
    sudo poweroff & # finally shutdown
}
trap cleanup EXIT

Ini bisa di akhir .bashrcopsi # 2, di suatu tempat di bagian atas skrip Anda untuk opsi # 1.

Mengapa tidak menggunakan poweroffdi akhir skrip?

Saya lebih suka menggunakan set -eo pipefaildi bagian atas skrip saya. Jika ada kesalahan, itu tidak akan gagal; itu akan berhenti mengeksekusi lebih banyak perintah. trapdari EXITsinyal harus mencakup kasus di mana script berakhir sebelum waktunya karena kesalahan.

Namun untuk tugas Anda, ini mungkin juga berarti mesin akan mati sebelum selesai.

Saya memiliki bashtemplate sederhana yang saya gunakan untuk membuat scripting lebih mudah di-debug; mungkin mungkin ada gunanya. Silakan lihat intinya .

sdkks
sumber
Setuju, dan untuk memastikan mungkin waktu penutupan hari dari cron. Ini rem orang mati.
mckenzm
@Abigail untuk skrip, harus di atas, karena .bashrcsaya lebih suka bagian bawah kalau-kalau ada hal lain yang menimpanya. Kekhawatiran Anda tampaknya tidak jelas, dapatkah Anda membagikan cuplikan contoh di repl.it mungkin?
sdkks
@ mckenzm saya tidak mengerti. Bisakah Anda membagikan kode sampel atau lebih banyak penjelasan?
sdkks
5

Mengelaborasi pada komentar @dirkt, Anda dapat memasukkan atperintah pada .bashrcatau .profileatau file mana saja yang digunakan shell Anda saat login untuk menjadwalkan shutdown otomatis 60 menit setelah login Anda.

Sesuatu seperti:

at now + 60 minutes -f /sbin/halt
Tuan Shunz
sumber
Tugas ini benar at. Anda juga dapat melihat attugas di/var/spool/
SDK
5
Saya akan menyarankan untuk tidak menggunakan atdalam konteks ini karena ia selamat dari reboot. Jika OP log in, shutdown manual dan kemudian login lagi dalam rentang satu jam, dia akan ditendang sebelum satu jam berlalu setelah login terakhirnya ketika proc shutdown terjadwal pertama.
Aaron
@ Harun itu benar. Belum memikirkan itu. Kegigihan boot adalah peringatan untuk solusi ini.
SDK
5

Berikut ini berjalan commanddengan parameter, dan jika selesai dengan sukses itu akan mematikan kotak segera, dengan asumsi pengguna dapat berjalan poweroff. Mungkin perlu digunakan sudo poweroff.

command --parameters && poweroff

Sedangkan yang berikut ini hanya berjalan poweroffsegera ketika perintah berakhir:

command --parameters ; poweroff

Jika menurut Anda perintah itu perlu waktu istirahat setelah selesai, jalankan

command --parameters ; sleep 3600 ; poweroff

Jika menurut Anda perintah itu bisa berjalan lembur, Anda bisa membatasi itu menjadi satu jam:

timeout 1h command --parameters ; poweroff

timeoutadalah bagian dari coreutilspaket sehingga Anda mungkin sudah memilikinya.

Criggie
sumber
3

Jika Anda benar-benar peduli dengan keamanan, gunakan timer outlet mekanis pada catu daya. Cukup atur kapan saja Anda ingin mematikannya. Dengan cara ini tidak ada yang bisa login dari jarak jauh dan menonaktifkan shutdown. Anda membutuhkan akses fisik.

gogator
sumber
2
Sistem file rusak?
Xen2050
@ Xen2050 bukan masalah pada sistem file modern (penjurnalan).
Tom
1
@ Tom Apakah Anda memiliki sumber untuk umount paksa tidak akan pernah menyebabkan korupsi sistem file jika ada penjurnalan? Kedengarannya baru bagi saya, saya ingin membacanya. Paling tidak itu harus menandai sistem file sebagai kotor, memaksa fsck kan?
Xen2050
1
Dalam kebanyakan kasus, itu hanya harus memutar ulang jurnal dan selesai dengannya. Powerdown seharusnya tidak menyebabkan kerusakan filesystem pada filesystem yang dijurnal, meskipun tidak ada jaminan kecuali Anda menggunakan filesystem seperti ZFS yang khusus dirancang untuk kasus ini.
Tom
1
Pemutaran ulang jurnal bisa gagal - saya mengalami sesi fsck yang sangat sulit beberapa minggu yang lalu setelah pemadaman listrik ½ detik ke mesin tanpa UPS. Itu menggunakan ext4 dengan jurnal; itu tidak sepenuhnya tak terkalahkan!
Toby Speight
2

Jika Anda berada di systemdmesin, Anda dapat menggunakan timer monoton

Unit pengatur waktu /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

Unit pengatur waktu /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

[Service]
ExecStart=/sbin/poweroff --force --no-wall
Type=oneshot

Ini diaktifkan melalui

# systemctl enable shutdown_after_an_hour.timer

Statusnya (khususnya berapa banyak waktu yang tersisa sebelum penutupan) tersedia melalui

# systemctl list-timers shutdown_after_an_hour.timer

Ini akan bekerja pada reboot berikutnya, itu tidak berguna untuk systemctl startitu selama sesi ketika itu dibuat karena itu tidak akan berfungsi (karena itu tidak dipicu selama reboot) atau mematikan mesin segera jika melewati satu jam. Saya tidak tahu yang mana yang akan terjadi, saya belum pernah menguji kasus khusus itu.

WoJ
sumber
1

Cobalah untuk meletakkan skrip ( sudo shutdown -P 3600) di /etc/init.ddirektori untuk menjalankannya secara otomatis saat startup.

Atau coba gunakan anacron, tambahkan perintah dalam /etc/anacrontabfile. Saya juga menyarankan untuk menggunakan nohupdi depan perintah untuk memastikan bahwa perintah masih berfungsi setelah keluar.

Saveriofr
sumber
1
Bergantung pada distro, itu mungkin tidak dapat dijalankan dengan hanya berada di init.d
sdkks
@ skdkks, Anda benar. Anacron juga dapat dipertimbangkan. menempatkan script di / etc / anacrontab, juga digunakan dengan 'nohup' pada saat logout.
Saveriofr
1
@Saveriofr Anda dapat mengedit jawaban Anda untuk meningkatkan kualitasnya (lebih baik daripada mengirim info tambahan sebagai komentar).
Anthony G - keadilan untuk Monica
1

Leverage File Keluar Shell Anda

Jika Anda hanya membutuhkan server untuk tugas-tugas interaktif atau non-interaktif yang dimulai oleh UID Anda, pertimbangkan untuk memasukkan perintah mematikan ke file ~ / .bash_logout Anda . The GNU Bash Pedoman mengatakan:

Ketika shell login interaktif keluar, atau shell login non-interaktif mengeksekusi perintah exit builtin, Bash membaca dan mengeksekusi perintah dari file ~ / .bash_logout, jika ada.

Jadi, menambahkan "sudo poweroff" atau mirip dengan file logout Anda akan mematikan server segera setelah Anda keluar dari sesi Anda saat ini, atau ketika sesi Bash non-interaktif panggilan exit. Anda juga dapat memilih untuk menggunakan pada atau melewatkan waktu tunda untuk shutdown jika Anda lebih suka menunda shutdown.

Untuk pendekatan yang lebih interaktif, Anda dapat memasukkan Bashism berikut ke dalam file logout Anda:

# Shutdown unless N or n is pressed within 30 seconds.
shopt -s nocasematch
read -t 30 -N 1 -p 'Shutdown now? (Y/n) '
[[ "$REPLY" =~ n ]] || sudo poweroff

Peringatan

Ada beberapa peringatan yang harus Anda ingat tentang solusi ini:

  • Ini mungkin akan berfungsi bahkan di bawah terminal yang dimulai oleh X Windows, tetapi mungkin tidak akan bekerja untuk sesi X11 yang tidak diluncurkan oleh startxatau serupa.
  • Jika Anda memiliki skrip non-interaktif yang memanggil exit, Anda mungkin mengalami penghentian yang tidak Anda harapkan.
  • File sudoers Anda mungkin meminta kata sandi jika Anda belum menentukan NOPASSWDperintah shutdown, atau jika Anda belum menelepon sudo -vsebelum menjalankan perintah shutdown Anda.
  • Mungkin ada kasus tepi lain yang belum saya pikirkan.

Singkatnya, Anda mungkin ingin mempertimbangkan apakah pendekatan ini memenuhi kebutuhan Anda yang sebenarnya, atau apakah pendekatan yang sama sekali berbeda seperti memantau tidak adanya pengguna yang masuk atau beberapa alternatif lain adalah taruhan yang lebih baik. Jarak tempuh Anda pasti akan bervariasi.

CodeGnome
sumber