sudo dalam skrip non-interaktif

9

Aku punya script yang mengeksekusi tiga fungsi: A && B && C.

Fungsi Bperlu dijalankan sebagai pengguna super, sementara Adan Ctidak.

Saya punya beberapa solusi tetapi tidak ada yang memuaskan:

  1. sudo seluruh skrip: sudo 'A && B && C'

    Tampaknya itu ide buruk untuk dijalankan Adan Csebagai pengguna super jika tidak diperlukan

  2. buat skrip menjadi interaktif: A && sudo B && C

    Saya mungkin harus mengetikkan kata sandi, tetapi saya ingin agar skrip saya non-interaktif, karena setiap fungsi memerlukan waktu, dan saya tidak ingin skrip menunggu. Yah, itu juga mengapa itu skrip di tempat pertama, jadi saya tidak harus melihatnya berjalan.

  3. Solusi bodoh: sudo : && A && sudo -n B && C

    Pertama tampaknya bodoh untuk menjalankan no-op sudopertama, dan juga saya harus mengatakan bahwa A tidak akan mengambil lebih dari $sudo_timeout.

  4. Solusi hipotetis (Saya harap Anda memberi tahu saya ada):

    sudo --store-cred 'A && sudo --use-cred-from-parent-sudo B && C'

    Itu akan meminta kata sandi saya di awal, dan kemudian menggunakan kredensial itu hanya ketika diperlukan.

Apa pendapat Anda tentang semua ini? Saya akan sangat terkejut bahwa tidak ada solusi untuk masalah itu, karena saya pikir itu adalah masalah yang cukup umum (bagaimana dengan make all && sudo make install)

Antoine Pelisse
sumber
3
Anda bisa membuat skrip yang Anda jalankan dengan sudo, tetapi dalam skrip jalankan bagian Adan Csecara eksplisit menggunakan su -l some_non_priviliged_user. Tidak ada masalah batas waktu, dan tidak ada privelig untuk A dan C. Saya tidak berpikir bahwa 4 mungkin, sudotampaknya "keadaan global" bagi pengguna.
Anthon

Jawaban:

7

Saya pikir hal terbaik yang dapat Anda lakukan adalah meluncurkan skrip dengan sudodan kemudian meluncurkan proses yang ingin Anda jalankan sebagai pengguna normal secara eksplisit dengan su useratau sudo -u user:

#!/usr/bin/env bash

## Detect the user who launched the script
usr=$(env | grep SUDO_USER | cut -d= -f 2)

## Exit if the script was not launched by root or through sudo
if [ -z $usr ] && [ $USER = "root" ]
then
    echo "The script needs to run as root" && exit 1
fi

## Run the job(s) that don't need root
sudo -u $usr commandA

## Run the job that needs to be run as root
commandB
terdon
sumber
9

Tambahkan skrip Anda ke /etc/sudoersfile dengan NOPASSWDatribut, sehingga diizinkan untuk berjalan tanpa diminta kata sandi. Anda dapat mengikat ini ke pengguna tertentu (atau set pengguna), atau membiarkannya dijalankan sudooleh siapa saja di sistem Anda.

Baris sampel untuk skrip yang dipanggil /usr/local/bin/bossymungkin terlihat seperti ini

ALL ALL = (root) NOPASSWD: /usr/local/bin/bossy

Dan Anda kemudian akan menggunakan sesuatu seperti ini

A && sudo bossy && C

Untuk contoh ini saya berasumsi PATHtermasuk /usr/local/bin. Jika tidak, gunakan saja path lengkap ke skrip, yaitusudo /usr/local/bin/bossy

roaima
sumber
Suara positif untuk pendekatan yang paling aman.
eyoung100
0

Anda mungkin ingin menggunakan !requirettyopsi ini sudoserta NOPASSWDopsi. Namun perlu diingat ini mengurangi keamanan.

Steve Wills
sumber
1
Seperti masalah didefinisikan sebagai tidak ingin script untuk menjadi interaktif, # 2 dengan /etc/sudoersentri untuk pengguna untuk menjalankan perintah Bdengan NOPASSWDadalah jawaban yang tepat.
Andrew
Itu "kamu bisa melakukan X atau Y", itu adalah "kamu bisa melakukan X dan Y". Hanya keduanya yang akan menyelesaikan masalah. Mungkin saya harus menuliskan kembali jawaban saya.
Steve Wills
0

Membangun jawaban saya untuk pra-otorisasi sudo? (Agar bisa dijalankan nanti) , tulis dua skrip:

  • ABC_script:

    #!/bin/sh
    sudo -b ./B_script
    A  &&  > A_is_done
    while [ ! -f B_is_done ]
    do
            sleep 60
    done
    rm -f B_is_done
    C
  • B_script:

    #!/bin/sh
    while [ ! -f A_is_done ]
    do
            sleep 60
    done
    rm -f A_is_done
    B  &&  > B_is_done

Jalankan ./ABC_script:

  • Itu akan berjalan sudo -b ./B_script. Ini meminta kata sandi ( segera setelah Anda menjalankan ABC_script). Dengan asumsi bahwa kata sandi yang benar dimasukkan, kata kunci itu akan muncul B_scriptdi b ackground (karena -btelah ditentukan) sebagai root. Ini tampaknya setara dengan sudo sh -c "./B_script &".
  • B_scriptmulai berjalan secara tidak sinkron, bersamaan dengan ABC_scriptB_scriptmenguji keberadaan file yang dipanggil A_is_done dan loop sampai muncul.
  • Secara paralel, ABC_scriptberjalan A. Jika / ketika Aselesai dengan sukses, skrip membuat file bernama A_is_done.
  • ABC_scriptkemudian menguji keberadaan file yang dipanggil B_is_done dan loop sampai muncul.
  • Secara paralel, B_scriptmendeteksi keberadaan A_is_donedan keluar dari loop. Ini menghapus A_is_donefile dan berjalan B. Ingat, B_scriptberjalan sebagai root, jadi itu berjalan Bsebagai root. Jika / ketika Bselesai dengan sukses, skrip membuat file yang dipanggil B_is_donedan keluar.
  • Secara paralel, ABC_scriptmendeteksi keberadaan B_is_donedan keluar dari loop. Ini menghapus B_is_donefile. Ingat, B_scriptjalankan sebagai root, sehingga B_is_donedimiliki oleh root, dan Anda ingin menggunakannya rm -funtuk menghindari permintaan konfirmasi. ABC_scriptlalu lari Cdan keluar.

Catatan untuk penyempurnaan lebih lanjut:

  • ABC_scriptmungkin harus dijalankan B_scriptoleh jalur absolut daripada ./.
  • Daripada A_is_donedan B_is_done, ABC_scriptmungkin harus menghasilkan nama file acak dan unik.
  • Perlu ada ketentuan untuk skrip yang menunggu giliran untuk diberi tahu jika program yang ditunggu telah selesai tetapi gagal. (Saat ini, jika Agagal, kedua skrip masuk ke loop tunggu tanpa batas.) Ini bisa sesederhana mengubah

    A  &&  > A_is_done

    untuk

    A; echo $? > A_is_done

    dan kemudian memodifikasi spin-tunggu untuk membaca X_is_donefile, dan lanjutkan jika itu berisi 0 dan keluar sebaliknya.

Scott
sumber
-3

Bodoh. gunakan banyak baris.

if A; then

    if sudo B ; then
        C
    fi
fi
Robert Jacobs
sumber
bagaimana itu menyelesaikan salah satu keprihatinan saya? Masalahnya tidak ada hubungannya dengan&&
Antoine Pelisse
&& menghentikan eksekusi ketika perintah pertama gagal. Pernyataan if melakukan hal ini dengan lebih kasar. Maksud saya adalah menyelesaikan pekerjaan Anda, meskipun itu tidak cantik.
Robert Jacobs
1
Hal ini tidak lebih dari sebuah versi yang lebih verbose dari opsi 2: A && sudo B && C. Seperti yang dijelaskan Antoine dalam pertanyaan; ini tidak meminta kata sandi sampai Aselesai, dan dia tidak ingin harus menunggu untuk itu, atau skrip menunggu untuknya.
Scott