Bagaimana ini '&' di akhir perintah saya, membuat skrip jadi cepat?

18

Sambil menyelesaikan beberapa tantangan KKP online, saya menemukan situasi di mana saya perlu memperkuat server. Ini adalah kode yang saya tulis:

#!/bin/bash

for i in {0..9}{0..9}{0..9}{0..9} 
    do
    echo "Now trying code.."
    echo $i
    echo "a fixed string" $i | nc localhost *port here* >> /tmp/me/dump.txt
    done

Ini luar biasa, sangat lambat . Saya perlu mencoba kombinasi dari 1000 hingga 9999 dan ini membutuhkan waktu sekitar 5 detik untuk setiap 10 percobaan. Kemudian, mengikuti saran, saya meletakkan tanda '&' di akhir baris ini:

   echo "a fixed string" $i | nc localhost *port here* >> /tmp/me/dump.txt &

Dan, ia mencoba kombinasi 100-an dalam hitungan detik. Saya sangat terkejut. Bisakah seseorang menjelaskan logikanya kepada saya? Apa yang dilakukan '&'?

pelajarX
sumber
3
Saya sarankan Anda membaca manual shell Anda. &membuat perintah berjalan di latar belakang, itu saja. Itu tidak membuatnya lebih cepat atau apa pun. Baca manual shell yang Anda gunakan (saya asumsikan bash) manual.
polemon
Itu membuatnya berjalan di latar belakang, Anda harus melihatnya itu benar-benar selesai.
DisplayName
7
Anda tidak ingin menguji di bawah 1000? Silakan gunakanfor i in {1000..9999}
Walter A
2
Mungkin itu memang membuat skrip berjalan lebih cepat karena port-port sekarang kehabisan waktu secara paralel. Anda harus memasukkan waitdi bagian akhir.
Bratchley
Apakah kamu melihat nc -z localhost 1000-2000?
Walter A

Jawaban:

30

Menambahkan &memunculkan proses latar belakang.

Jika Anda menulis a; b, itu akan menjalankan perintah a, tunggu sampai selesai, kemudian jalankan perintah b, secara berurutan.

Jika Anda menulis a & b, itu akan muncul asebagai proses latar belakang. Itu tidak akan menunggu sampai selesai, dan itu akan mulai berjalan bsegera. Ini akan menjalankan keduanya sekaligus.

Anda dapat melihat apa yang dilakukannya dengan bereksperimen di shell. Jika Anda telah Xmenginstal, xtermadalah cara yang baik untuk melihat apa yang terjadi: mengetik

$ xterm

akan menyebabkan jendela terminal lain terbuka, dan yang pertama akan menunggu sampai Anda menutupnya. Hanya ketika Anda menutupnya Anda akan mendapatkan shell Anda kembali. Jika Anda mengetik

$ xterm &

maka itu akan menjalankannya di latar belakang, dan Anda akan mendapatkan shell Anda segera, sementara xtermjendela juga akan tetap terbuka.

Jadi, jika Anda menulis

echo "a fixed string" $i | nc localhost *port here* >> /tmp/me/dump.txt

itu membuat koneksi, mengirim string, menyimpan apa yang keluar dalam file, dan hanya kemudian pindah ke yang berikutnya.

Menambahkan &membuatnya tidak menunggu. Ini akan berakhir menjalankan semua sepuluh ribu dari mereka lebih atau kurang secara bersamaan.

Skrip Anda tampaknya "berakhir" lebih cepat, karena mungkin itu tidak benar-benar selesai pada saat itu. Itu hanya membuat sepuluh ribu pekerjaan latar belakang, dan kemudian mengakhiri latar depan.

Ini juga berarti bahwa, dalam kasus Anda, itu akan mencoba membuka sepuluh ribu koneksi lebih atau kurang sekaligus. Bergantung pada apa yang ujungnya bisa tangani, beberapa dari mereka mungkin gagal. Bukan hanya itu, tetapi tidak ada jaminan bahwa mereka akan berjalan berurutan, pada kenyataannya mereka hampir pasti tidak akan, jadi apa yang sebenarnya akan berakhir /tmp/me/dump.txtadalah dugaan siapa pun.

Apakah Anda memeriksa apakah outputnya benar?

marinus
sumber
2
Ya, saya memecahkan tantangan. Server merespons dengan kata sandi jika kode yang benar diberikan kepadanya. Saya mengeksekusi perintah ini untuk memeriksa 'dump.txt': $ cat dump.txt | sort | uniq -u ..dan baris yang berisi kata sandi yang benar terungkap kepada saya.
learnerX
16
@intellikid: Saya tidak bermaksud kasar, tetapi berhasil karena keberuntungan. Tidak hanya urutan tidak masalah, respons server lebih kecil dari ncbuffer tulis. Seandainya tidak demikian, respons server kemungkinan besar akan disisipkan. Yaitu, jika Anda memiliki buffer tulis 1 byte, dan tanggapannya 1111dan 2222, Anda mungkin akan melihat sesuatu seperti 11221212daripada dipisahkan dengan rapi 1111 2222.
marinus
Ya, saya menyadari itu. Itu sebabnya saya memainkan wargames ini. Saya belajar di setiap level. Terima kasih telah membantu pembelajaran itu.
learnerX
2

Perintah nc (netcat) mahal, waktu bijaksana. Perlu terhubung ke server jarak jauh, mengirim data, menunggu respons, dan mengembalikannya.

Dengan menggunakan & Anda pada dasarnya forking perintah itu dalam proses latar belakang (itu disebut "pekerjaan"). Dengan sendirinya itu tidak membuatnya berjalan lebih cepat. Tetapi itu berarti loop Anda tidak lagi diblokir, dan dapat melakukan iterasi berikutnya (dengan nc berikutnya) sudah.

Jadi pada dasarnya, speedup Anda disebabkan oleh membuat semua koneksi jarak jauh ini secara paralel di mana jika tidak mereka harus menunggu yang sebelumnya selesai.

Btw, tergantung pada terminal Anda, perintah gema juga dapat memperlambat loop Anda (kadang-kadang mereka harus menunggu sampai ada ruang di buffer tulis).

Leon
sumber