Làm thế nào để tôi biết nếu một lệnh đang chạy hoặc chờ người dùng nhập liệu?


14

Trên dòng lệnh, tôi gõ một lệnh và nhấn enter. Nó không đầu ra bất cứ điều gì. Làm thế nào để tôi biết nếu nó đang chạy và chưa xuất ra, hoặc nó yêu cầu đầu vào của người dùng?


Nếu nó đang chờ thì bạn sẽ không nhận được PS1lời nhắc.
Prvt_Yadav

1. Vui lòng cho chúng tôi biết đó là chương trình nào (đó là im lặng) và chúng tôi có thể cho bạn lời khuyên chính xác hơn về những gì mong đợi và cách kiểm tra nó; 2. Bạn có muốn nhận thông báo không, khi chương trình cuối cùng yêu cầu nhập liệu hoặc đã kết thúc (để một cái gì đó được ghi vào cửa sổ thiết bị đầu cuối?
sudodus 14/2/19

nếu có một đầu vào dự kiến ​​tôi sẽ giả sử bạn nhận được lời nhắc với một thông báo ở phía trước yêu cầu đầu vào.
Rinzwind

5
@Rinzwind - Đó là một giả định kém. Ví dụ đầu tiên để tâm là catlệnh. Chỉ cần gõ một catmình và nó sẽ đợi đầu vào từ stdin, nhưng không đưa ra lời nhắc. Nhiều lệnh khác hoạt động tương tự vì chúng mong đợi đầu vào từ stdin hoặc tệp, nhưng không phân biệt giữa các nguồn đầu vào khác nhau (thiết bị đầu cuối tương tác, đường ống, tệp ...).
Dave Sherohman

Câu trả lời:


15

Có một số cách tiếp cận:

  1. Hãy thử tín hiệu đầu vào cuối năm : Nếu không có đặc quyền superuser rất khó để biết những gì đang xảy ra bên dưới nắp ca-pô. Những gì có thể được thực hiện là nhấn Ctrl+ d. Thiết bị đầu cuối và tiện ích trong chế độ chính tắc gửi tất cả văn bản có sẵn đến read()tòa nhà khi nhận được tín hiệu EOT bị ràng buộc với tổ hợp phím này và nếu không có đầu vào - read()trả về trạng thái thoát âm mà hầu hết các tiện ích chấp nhận là tín hiệu để thoát. Do đó, nếu một tiện ích đang chờ đầu vào, nó sẽ thoát khi nhận được tổ hợp phím. Mặt khác, tiện ích là chạy các tác vụ hoặc không được viết đúng.

  2. Gián điệp trên các tòa nhà chọc trời : Nếu bạn có đặc quyền siêu người dùng, bạn có thể chạy stracetrong một thiết bị đầu cuối khác để xem những gì hiện đang được thực hiện. Cho rằng bạn cần phải tìm ra PID của chương trình. Chẳng hạn, trong một tab thiết bị đầu cuối khác pgrep -f firefoxcó thể chạy 1234 như ví dụ và sau đó sudo strace -f -p 1234. Nếu đầu ra mà bạn nhìn thấy bị kẹt trên read()tòa nhà chọc trời, điều đó có nghĩa là lệnh có thể đang chờ đầu vào. Mặt khác, nếu bạn thấy các tòa nhà chọc trời đang chạy, thì lệnh đang làm một cái gì đó khác. Xem một câu hỏi liên quan để sử dụng stracecũng tìm hiểu xem lệnh chạy dài đã thoát chưa.

  3. Sử dụng các phương thức riêng của lệnh : Trong số những thứ khác, các tiện ích như ddtín hiệu sử dụng. Chẳng hạn, nếu bạn sử dụng kill -USR1 1234(trong đó 1234 là PID của ddlệnh đang chạy ), nó sẽ in ra để tiêu hao số lượng byte hiện đang được xử lý. Tất nhiên, điều này đòi hỏi phải biết về hành vi như vậy của lệnh ở nơi đầu tiên. Hai phương pháp trên chung chung hơn và không yêu cầu kiến ​​thức sâu sắc về từng hành vi của lệnh (mặc dù tốt nhất là bạn nên biết những gì bạn đang thực hiện - nếu không, bạn có nguy cơ chạy một lệnh có thể gây thiệt hại).


+1. Cảm ơn stracephương pháp :-) Nhưng các phương pháp đơn giản hơn cũng hữu ích (chung hoặc cụ thể cho từng chương trình). Một số trong số họ làm việc mà không có đặc quyền siêu người dùng. Ví dụ: kiểm tra xem có ddđang làm gì không và kiểm tra tại sao lại grep --color asdfim lặng chờ đợi.
sudodus

@sudodus Ah, nhắc nhở tốt về ddtôi sẽ thêm cái đó.
Sergiy Kolodyazhnyy

Bạn không cần đặc quyền siêu người dùng để gỡ lỗi một quy trình thuộc sở hữu của người dùng của bạn. Chà, trừ khi bạn không thiết lập hệ thống phù hợp .
Ruslan

6

Làm thế nào để biết nếu một chương trình đang chạy hoặc muốn người dùng nhập liệu

Nó phụ thuộc vào chương trình và cách bạn gọi nó.

  • Thông thường nhưng không phải lúc nào cũng sẽ có một lời nhắc, điều đó chỉ ra rằng chương trình đang yêu cầu đầu vào.

  • Nếu bạn không chắc chắn, bạn có thể kiểm tra xem quy trình của chương trình có bận không

    • sử dụng CPU - sử dụng tophoặchtop

    • đọc hoặc viết - sử dụng sudo iotop -o

  • Và khi chương trình kết thúc, bạn sẽ thấy dấu nhắc của shell.

Vỏ sò running

Tôi đã có một shellscript để kiểm tra xem một chương trình có đang chạy hay không, và bây giờ tôi đã thêm tùy chọn -sđể làm cho nó chạy sudo strace -f -p <PID>(theo câu trả lời của Sergiy Kolodyazhnyy) khi tìm thấy ...

Shellscript sử dụng

  • ps -ef để tìm phần lớn các chương trình
  • systemctl is-active --quiet để tìm một số chương trình
  • và nếu bạn muốn stracetrong một xtermcửa sổ.

    Cài đặt xtermnếu bạn muốn sử dụng straceđể xem hoạt động của một chương trình.

Sử dụng

$ ./running
Usage:    ./running <program-name>
          ./running <part of program name>
Examples: ./running firefox
          ./running term                     # part of program name
          ./running dbus
          ./running 'dbus-daemon --session'  # words with quotes
          ./running -v term                  # verbose output
          ./running -s term                  # strace checks activity

Bạn có thể cài đặt shellscript runningvào một thư mục PATHnếu bạn muốn truy cập dễ dàng vào nó.

Mã shellscript

#!/bin/bash

# date        sign     comment
# 2019-02-14  sudodus  version 1.0

verbose=false
strace=false
if [ "$1" == "-v" ]
then
 verbose=true
 shift
fi
if [ "$1" == "-s" ]
then
 strace=true
 shift
fi

if [ $# -ne 1 ]
then
 echo "Usage:    $0 <program-name>
          $0 <part of program name>
Examples: $0 firefox
          $0 term                     # part of program name
          $0 dbus
          $0 'dbus-daemon --session'  # words with quotes
          $0 -v term                  # verbose output
          $0 -s term                  # strace checks activity"
 exit
fi

inversvid="\0033[7m"
resetvid="\0033[0m"
redback="\0033[1;37;41m"
greenback="\0033[1;37;42m"
blueback="\0033[1;37;44m"

runn=false
#tmpfil=$(mktemp)
tmpdir=$(mktemp -d)
tmpfil="$tmpdir/tmpfil"
vtfile="$tmpdir/vtfile"
vthead="$tmpdir/vthead"

# check by systemctl

systemctl is-active --quiet "$1"
if [ $? -eq 0 ]
then
 echo "systemctl is-active:"
 runn=true
fi

# check by ps

ps -ef | tr -s ' ' ' ' | cut -d ' ' -f 8- | grep "$1" | grep -vE -e "$0 *$1" -e "$0 *.* *$1" -e "grep $1" | sort -u > "$tmpfil"
#cat "$tmpfil"
if $verbose || $strace
then
 ps -ef |head -n1 > "$vthead"
 ps -ef | grep "$1" | grep -vE -e "$0 *.* *$1" -e "grep $1" | sort -u > "$vtfile"
fi

tmpstr=$(head -n1 "$tmpfil")
#echo "tmpstr=$tmpstr"
tmpess=$(grep -om1 "$1" "$tmpfil")
#echo "tmpess=$tmpess"
if [ "$tmpstr" == "$1" ] || [ "${tmpstr##*/}" == "$1" ] || [ "${1##*/}" == "${0##*/}" ] || [ "$tmpess" == "$1" ]
then
 echo "ps -ef: active:"
 runn=true
 if $verbose
 then
  cat "$vthead" "$vtfile"
 fi
elif test -s "$tmpfil"
then
 if $runn
 then
  echo "----- consider also ------------------------------------------------------------"
  if $verbose
  then
   cat "$vthead" "$vtfile"
  else
   cat "$tmpfil"
  fi
  echo "--------------------------------------------------------------------------------"
 else
  echo "----- try with: ----------------------------------------------------------------"
  if $verbose
  then
   cat "$vthead" "$vtfile"
  else
   cat "$tmpfil"
  fi
  echo "--------------------------------------------------------------------------------"
 fi
fi

if $runn
then
 echo -en "$greenback '$1"
 if [ "$tmpstr" != "$tmpess" ]
 then
  echo -n " ..."
 fi
 echo -e "' is running $resetvid"

 if $strace
 then
  which xterm
  if [ $? -eq 0 ]
  then
   pid=$(head -n1 "$vtfile" | sed 's/^ *//' | tr -s ' ' '\t' | cut -f 2)
   echo "checking pid=$pid; quit with 'ctrl + c' in the xterm window"
   xterm -title "'strace' checks '$1'" 2> /dev/null -e sudo strace -f -p $pid
  else
   echo "Please install 'xterm' for this function to work"
   exit
  fi
 fi
else
 inpath=$(which "$1")
 if [ "$inpath" == "" ]
 then
  echo -e "$redback no path found to '$1' $resetvid"
 else
  echo -e "$blueback '$1' is not running $resetvid"
 fi
fi
rm -r "$tmpdir"

Bản giới thiệu

Kiểm tra các cửa sổ đầu cuối trong Lubfox (LXTerminal bắt đầu như x-terminal-emulatorvà các gnome-terminalcửa sổ tùy chỉnh ),

$ running -v -s term 
----- try with: ----------------------------------------------------------------
UID        PID  PPID  C STIME TTY          TIME CMD
sudodus   2087  1384  0 13:33 ?        00:00:00 x-terminal-emulator
sudodus   2108  1269  0 13:33 ?        00:00:17 /usr/lib/gnome-terminal/gnome-terminal-server
--------------------------------------------------------------------------------
 no path found to 'term' 

$ running -v -s x-terminal-emulator
ps -ef: active:
UID        PID  PPID  C STIME TTY          TIME CMD
sudodus   2087  1384  0 13:33 ?        00:00:00 x-terminal-emulator
 'x-terminal-emulator' is running 
/usr/bin/xterm
checking pid=2087; quit with 'ctrl + c' in the xterm window

rất nhiều hoạt động ngay khi con trỏ ở trong cửa sổ terminal.

nhập mô tả hình ảnh ở đây

Bắt đầu grep(chờ đầu vào từ /dev/stdin)

$ grep -i --color 'hello'
asdf
Hello World    
Hello World

Kiểm tra nó

$ running -s grep
ps -ef: active:
 'grep ...' is running 
/usr/bin/xterm
checking pid=14982; quit with 'ctrl + c' in the xterm window

Không có nhiều hoạt động và bạn có thể xác định những gì đang xảy ra.

nhập mô tả hình ảnh ở đây


Tốt đề cập đến iotop, mặc dù việc sử dụng CPU có thể không nhất thiết là một chỉ báo nếu một quá trình bận rộn. Một chương trình được viết bằng C và được tối ưu hóa có thể sử dụng CPU tối thiểu. Một số chỉ báo tôi đã viết bằng Python lên lịch để thực hiện một tác vụ lặp đi lặp lại, do đó, nó có thể sử dụng CPU để cập nhật menu chỉ báo trong giây lát và sau đó chỉ ngồi đó.
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy, Vâng, bạn nói đúng về điều đó. Các stracephương pháp là tốt hơn, nhưng có lẽ không cần thiết hoặc không có sẵn.
sudodus

Đã đồng ý. Tôi không nghĩ rằng nó được cài đặt sẵn với Ubuntu và có thể là quá mức cần thiết.
Sergiy Kolodyazhnyy

1

Không chắc chắn nếu bạn vẫn cần điều này, nhưng vẫn là một mẹo hữu ích để biết: nếu chương trình dường như thoát mà không có bất kỳ đầu ra nào, bạn có thể kiểm tra xem nó có chạy trong nền không bằng cách thực hiện

ps -efa | grep "program_name"

Chúc mừng!


1

Nếu bạn đang chạy shell trong thiết bị đầu cuối, ví dụ như trình giả lập thiết bị đầu cuối hoặc phiên ssh thông thường, trình bao của bạn gần như chắc chắn đã kích hoạt kiểm soát công việc. Điều này làm cho việc có được một câu trả lời cho câu hỏi của bạn siêu dễ dàng trong hầu hết các trường hợp.

Nhập Ctrl+Zđể tạm dừng quá trình và sau đó bgtiếp tục quá trình trong nền, sau đó nhập một dòng trống vào trình bao để nó kiểm tra xem chương trình có bị dừng bởi tín hiệu hay không.

Nếu quá trình đang cố đọc từ thiết bị đầu cuối, nó sẽ ngay lập tức nhận được SIGTTINtín hiệu và sẽ bị treo. (Khi bật chức năng kiểm soát công việc, hệ thống chỉ cho phép một quá trình tại một thời điểm để đọc từ thiết bị đầu cuối.) Shell sẽ báo cáo điều này. Sau đó, bạn có thể nhập fgđể tiếp tục quá trình ở nền trước và sau đó nhập đầu vào để chương trình đọc như bình thường.

mp@ubuntu:~$ sleep 30 # a program that is not reading from the terminal
^Z
[1]+  Stopped                 sleep 30
mp@ubuntu:~$ bg
[1]+ sleep 30 &
mp@ubuntu:~$ 
mp@ubuntu:~$ 


mp@ubuntu:~$ cat - # a program that is reading from the terminal
^Z
[1]+  Stopped                 cat -
mp@ubuntu:~$ bg
[1]+ cat - &
mp@ubuntu:~$ 
[1]+  Stopped                 cat -
mp@ubuntu:~$ jobs -l
[1]+  3503 Stopped (tty input)     cat -
mp@ubuntu:~$ fg
cat -
hi
hi

Một số chương trình, chẳng hạn như trình soạn thảo, sẽ bẫy hoặc bỏ qua tín hiệu được tạo bởi Ctrl+Zhoặc đặt thiết bị đầu cuối vào chế độ trong đó các ký tự điều khiển thậm chí không tạo tín hiệu. Bạn sẽ cần phải sử dụng các kỹ thuật tiên tiến hơn trong trường hợp này, chẳng hạn như sử dụng straceđể xem nếu quá trình này được thực hiện read, select, pollvv

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.