Bagaimana cara saya membunuh proses yang mati tetapi mendengarkan?

48

Saya sedang mengembangkan sebuah aplikasi yang mendengarkan pada port 3000. Rupanya ada sebuah instance dari itu masih mendengarkan port karena setiap kali saya memulainya, ia tidak dapat membuat pendengar (C #, TcpListener, tapi itu tidak relevan) karena port tersebut sudah diambil.

Sekarang, aplikasi tidak ada di Task Manager, jadi saya mencoba mencari PID-nya dan membunuhnya, yang menyebabkan hasil yang menarik ini:

C:\Users\username>netstat -o -n -a | findstr 0.0:3000
   TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       3116

C:\Users\username>taskkill /F /PID 3116
ERROR: The process "3116" not found.

Saya belum pernah melihat perilaku ini sebelumnya dan menganggapnya cukup menarik untuk melihat apakah ada yang punya solusi.

UPDATE: Saya memulai Process Explorer dan mencari 3000 dan menemukan ini:

<Non-existent Process>(3000): 5552

Saya mengkliknya dan memilih "Tutup Pegangan". Tidak lagi di Process Explorer, tetapi masih muncul di netstat dan masih menghentikan aplikasi dari memulai pendengar.

UPDATE 2: Ditemukan TCPView untuk Windows yang menunjukkan proses sebagai "<non-existent>". Seperti dengan CurrPorts, tidak ada yang terjadi ketika saya mencoba untuk menutup koneksi di alat ini.

Srekel
sumber
sedikit menyembuhkan penyakit dengan membunuh pasien, tetapi apakah itu berhenti jika Anda me-restart komputer?
Xantec
2
Sebenarnya, logout dan kembali lagi sudah cukup, tetapi saya sekarang sudah berhasil mereproduksinya jadi saya masih ingin mencari solusi yang lebih baik ...
Srekel
Periksa apakah ada program yang tercantum di sini yang membantu
Sathyajith Bhat
1
Dengan versi TCPView 3.05 saat ini "Tutup koneksi" dari menu konteks proses <non-exsitent> berhasil menutup koneksi dalam kasus saya dan membebaskan port.
Ventzy Kunev
1
Lihat juga serverfault.com/questions/181015/…
rogerdpack

Jawaban:

13

Untuk menghindari menunggu tanpa akhir pada soket, program Anda harus menggunakan fungsi setsockopt dengan parameter SO_REUSEADDR dan SO_RCVTIMEO:

SO_REUSEADDR : Allows the socket to be bound to an address that is already in use.
SO_RCVTIMEO : Sets the timeout, in milliseconds, for blocking receive calls. 
harrymc
sumber
1
Apakah ini membantu orang dengan masalah khusus ini (soket mendengarkan dengan proses mati)?
rustyx
12

Kami memiliki masalah yang sama dan menggunakan Process Explorer dari Microsoft Sysinternals untuk mencari ID proses yang tidak lagi ada.

Ternyata proses itu dirujuk oleh beberapa proses DrWatson. Membunuh proses-proses tersebut merilis port. DrWatson digunakan untuk mengirim dump memori ke Microsoft dan ini memakan waktu beberapa jam karena proses yang macet menampung beberapa puluh GB memori pada saat itu.

David
sumber
7

Saya pikir Anda harus mencoba CurrPorts

CurrPorts adalah perangkat lunak pemantauan jaringan yang menampilkan daftar semua port TCP / IP dan UDP yang saat ini dibuka di komputer lokal Anda. Untuk setiap port dalam daftar, informasi tentang proses yang membuka port juga ditampilkan, termasuk nama proses, path lengkap proses, informasi versi proses (nama produk, deskripsi file, dan sebagainya), waktu yang proses telah dibuat, dan pengguna yang membuatnya.

Selain itu, CurrPorts memungkinkan Anda untuk menutup koneksi TCP yang tidak diinginkan, mematikan proses yang membuka port, dan menyimpan informasi port TCP / UDP ke file HTML, file XML, atau ke file teks yang dibatasi tab.

CurrPorts juga secara otomatis menandai dengan warna merah muda yang mencurigakan port TCP / UDP yang dimiliki oleh aplikasi yang tidak dikenal (Aplikasi tanpa informasi versi dan ikon)

teks alternatif

Sathyajith Bhat
sumber
4
Itu muncul dalam daftar di bawah nama proses "Sistem". Saya mencoba mengklik kanan item untuk menutup paksa port tetapi tidak ada yang terjadi.
Srekel
7

Masalah yang mungkin terjadi adalah bahwa proses Anda telah memulai proses (anak) lain yang mewarisi pegangan soket, dan masih berjalan.

Ada berbagai cara untuk mencegah hal ini, misalnya: ProcessStartInfo.UseShellExecute = true;

Nick Westgate
sumber
1
Terima kasih, ini bagus. Saya menelepon subprocess.call(..., cwd=..., shell=True)sebagai peluncur aplikasi di server web python, dan ternyata saya harus membunuh semua proses anak untuk membebaskan soket. Yang aneh adalah saya menggunakan shell = True. Ini membuat saya kesal selama bertahun-tahun.
Daniel F
Saya tidak berpikir bahwa menggunakan shell menghasilkan perilaku ini. Jika Anda ingin menghentikan semua proses anak ketika orang tua meninggal, saya pikir cara yang benar adalah dengan membuat Obyek Pekerjaan dengan bendera JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE , tambahkan setiap proses anak dengan AssignProcessToJobObject , dan izinkan pegangan untuk menutup secara alami ketika proses induk keluar.
qris
1

Bisakah Anda melihat proses di Process Explorer ? Jika ya daripada Anda dapat membunuhnya dari sana, tetapi hanya setelah Anda menyelidiki apa itu sebenarnya (Anda dapat melihat semua dll dimuat ke dalam proses)

Jakub Konecki
sumber
1

Cobalah melemparkan bendera '-b' pada perintah netstat Anda. Ini akan memberi tahu Anda nama executable yang menggunakan port. Kemudian temukan proc itu di task manager dan bunuh di sana. Jika itu tidak berhasil, posting apa yang dapat dieksekusi yang membuat port terbuka.

Ge3ng
sumber
Saya tidak dapat mereproduksinya saat ini, tetapi saya cukup yakin bahwa karena setiap upaya lain (dan alat) untuk mencoba menemukan nama proses gagal, netstat tidak akan mampu melakukannya juga.
Srekel
1

Perlu menyebutkan istilah berlama-lama di sini.

Detail dapat ditemukan di http://msdn.microsoft.com/en-us/library/ms739165.aspx

Singkatnya: Ada opsi yang memberi tahu sistem soket untuk menjaga soket tetap terbuka bahkan setelah ditutup jika data yang tidak terkirim ada.

Dalam aplikasi C # Anda, Anda dapat menentukan opsi terkait melalui Socket.SetSocketOption: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Karena semua hal yang disebutkan terkait dengan pengiriman dan klien, tetapi kami memiliki masalah serupa di tempat kerja, beberapa pencarian lebih lanjut senang bahwa seseorang dapat menentukan opsi berlama-lama untuk pendengar seperti yang ditunjukkan dalam contoh di sini: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Beberapa rekan berbicara tentang port yang ditahan oleh OS setelah aplikasi penghentian / penutupan selama sekitar dua menit. Karena itu, akan menarik untuk mendengar apakah pelabuhan masih ditahan setelah waktu tertentu.

Andreas
sumber
Port dibuka lebih lama dari itu (tidak ingat berapa lama tapi mungkin sampai satu jam sebelum saya menyerah dan reboot).
Srekel
Saya tidak yakin apakah opsi berlama-lama relevan dengan kasus khusus ini, karena sepertinya hanya menentukan apa yang seharusnya terjadi setelah panggilan ke CloseSocket. Karena saya mematikan aplikasi, saya ragu bahwa fungsi dipanggil (?).
Srekel
1

Saya juga mengalami masalah ini. Akhirnya saya menemukan alasan saya. Ini disebabkan oleh proses utama yang memanggil proses anak oleh popen di c / c ++. Tetapi proses utama crash / shutdown sebelum memanggil pclose. Kemudian pelabuhan akan memperlakukan proses utama masih hidup dan masih mendengarkannya.

lori. pergilah
sumber
1
Saya menemukan jawaban ini di ServerFault bermanfaat: serverfault.com/a/273727/8856
Harriv
1

Saya punya masalah yang sama dengan xdebug, port kiri 9000 terbuka.

Saya berhasil menutup dengan cmd menggunakan "taskkill / pid xxxx".

Pid dari proses menggunakan port dapat diambil dengan "netstat -o".

Konfigurasi saya adalah memenangkan 7 home premium.

Christoforos
sumber
1

Saya memiliki masalah yang sama dan memperbaikinya dengan:

  • menemukan PID dengan netstat -o
  • Bunuh dengan proses xp

Menarik untuk dicatat bahwa netstat terkadang dapat mengembalikan pid tetapi bukan nama yang dapat dieksekusi yang sesuai!

eka808
sumber
1

Masalahnya dapat disebabkan jika proses mati telah memulai satu atau lebih proses anak. Jika

BOOL WINAPI CreateProcess(
_In_opt_    LPCTSTR               lpApplicationName,
_Inout_opt_ LPTSTR                lpCommandLine,
_In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_        BOOL                  bInheritHandles,
_In_        DWORD                 dwCreationFlags,
_In_opt_    LPVOID                lpEnvironment,
_In_opt_    LPCTSTR               lpCurrentDirectory,
_In_        LPSTARTUPINFO         lpStartupInfo,
_Out_       LPPROCESS_INFORMATION lpProcessInformation
);

digunakan untuk memulai proses anak, itu tergantung pada nilai pegangan warisan, begitu juga dengan

bInheritHandles = false 

Windows tidak akan memblokir port jika proses induk dihentikan dan proses klien masih berjalan.

V15I0N
sumber
1

melihat masalah yang sama ketika root menyebabkan beberapa proses anak dibuat mewarisi port, proses induk terhenti, sementara proses anak masih memegang port. Resolusi adalah untuk mengidentifikasi proses anak yang masih berjalan dan menghentikannya. Dalam contoh di sini PID proses yang tidak ada adalah 7336

> wmic process get processid,parentprocessid | findstr/i 7336
7336             23828

Untuk menghentikan proses ini:

> taskkill /f /pid 23828

Dan ini menyelesaikan masalah.

Michael
sumber
0

Saya kira Anda tidak menginstal firewall (atau mencoba tweeks jaringan Windows)?

Beberapa firewall menunjukkan perilaku semacam ini dan dapat membuat port tetap terbuka.

Jika Anda memilikinya, coba nonaktifkan lalu luncurkan program Anda dan tutup dan lihat apa yang terjadi.

William Hilsum
sumber
Sayangnya bukan pilihan, karena saya tidak memiliki kendali atas firewall di komputer saya.
Srekel
@ Karael - firewall apa itu? Ketika Anda mengalami masalah, saya pribadi akan berpikir yang menyebabkan masalah.
William Hilsum
0

Karena proses Anda terdaftar sebagai Sistem, kemungkinan besar Anda dapat membunuhnya pada prompt perintah "Sistem". Akun Sistem memiliki lebih banyak hak istimewa daripada administrator biasa.

Anda bisa mendapatkan "Sistem" cmd.exe dengan menjadwalkan tugas untuk cmd.exe (penjadwal berjalan sebagai Sistem):

at 15:23 /interactive "cmd.exe" 

Ubah waktu itu untuk sesuatu dalam waktu dekat. Pastikan juga Anda berada di konsol mesin (jika Anda berada di sesi server terminal reguler, Anda tidak akan melihat cmd.exe baru. Buat mstsclogin ke konsol). Saya kira ada cara lain untuk melakukan itu, tetapi ini berhasil bagi saya di masa lalu.

David Suarez
sumber
0

Saya punya masalah yang sama. Proses ini sedang di-debug saat crash, dan masih ada proses vsjitdebugger.exe dalam keadaan ditangguhkan yang masih ada, yang tampaknya merujuk pada proses yang sedang di-debug. Membunuh proses vsjitdebugger.exe menyelesaikan masalah.

gpvos
sumber
0

Penggunaan Hybrid dari TCPView dan Process Explorer bekerja untuk saya;) Saya pertama kali melihat ke id proses yang menggunakan port di TCPView. Mengisolasi proses di Process Explorer dan mematikan proses menggunakan Process Explorer.

Sathiya Narayanan
sumber