Buộc một bí danh 'đã thêm' vào mỗi lệnh


11

Có thể buộc thêm một bí danh thời gian (vì không có cách nào tốt hơn để diễn đạt nó) cho mỗi lệnh trong bash?

Ví dụ, tôi muốn có một người dùng cụ thể, bất cứ khi nào một lệnh được chạy, nó luôn được bao bọc bằng datetrước và sau, hoặc time.

Điều này là có thể, và, nếu vậy, làm thế nào?


Tôi đã nhìn trước đây và không thể tìm ra cách nào để làm chính xác điều này. Như Caleb nói, bạn có thể sử dụng preexec, nhưng bạn không muốn chạy nó bên trong preexec(ví dụ preexec() { time $1; }), vì shell vẫn chạy nó sau khi preexectrả về. Vì vậy, điều tốt nhất chúng ta có thể làm là một cái gì đó tương tự.
Mikel

@Mikel Tôi nghĩ rằng bạn có thể sử dụng preexec()hàm để thực sự bao bọc bất cứ thứ gì đang thực thi bằng cách tìm nạp lệnh, tự chạy nó từ bên trong hàm, sau đó trả về một số lỗi để shell không tiếp tục thực thi lệnh.
Caleb

Câu trả lời:


10

Bạn có thể ghi lại thời gian một dòng lệnh được bắt đầu và thời gian một dấu nhắc được hiển thị. Bash đã theo dõi ngày bắt đầu của mỗi dòng lệnh trong lịch sử của nó và bạn có thể lưu ý thời gian khi bạn hiển thị lời nhắc tiếp theo.

print_command_wall_clock_time () {
  echo Wall clock time: \
    $(($(date +%s) - $(HISTTIMEFORMAT="%s ";
                       set -o noglob;
                       set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"

Điều này chỉ cung cấp cho bạn độ phân giải thứ hai, và chỉ có thời gian đồng hồ treo tường. Nếu bạn muốn độ phân giải tốt hơn, bạn cần sử dụng một datelệnh bên ngoài hỗ trợ %Nđịnh dạng cho nano giây và DEBUGbẫy để gọi datetrước khi chạy lệnh theo thời gian.

call_date_before_command () {
  date_before=$(date +%s.%N)
}
print_wall_clock_time () {
  echo Wall clock time: \
    $((date +"$date_before - %s.%N" | bc))
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_command_wall_clock_time

Ngay cả với DEBUGbẫy, tôi không nghĩ có cách tự động hiển thị thời gian của bộ xử lý cho mỗi lệnh hoặc bị phân biệt đối xử nhiều hơn là nhắc nhở.


Nếu bạn sẵn sàng sử dụng một trình bao khác, đây là cách nhận báo cáo thời gian cho mọi lệnh trong zsh (điều này không khái quát cho các tác vụ khác):

REPORTTIME=0

Bạn có thể đặt REPORTTIMEthành bất kỳ giá trị số nguyên nào, thông tin về thời gian sẽ chỉ được hiển thị cho các lệnh được sử dụng nhiều hơn thời gian xử lý nhiều giây này.

Zsh lấy tính năng này từ csh nơi biến được gọi time.


3

Tùy chọn của bạn ở đây sẽ phụ thuộc vào vỏ của bạn. Trong zshđó, một hàm hook tiện lợi được gọi preexec()là chạy ngay trước bất kỳ lệnh shell tương tác nào. Bằng cách tạo một hàm với tên này, bạn có thể khiến mọi thứ được thực thi. Bạn cũng có thể theo dõi với một hàm được gọi precmd()sẽ chạy ngay trước khi lời nhắc tiếp theo được rút ra, nó sẽ ở ngay sau khi lệnh của bạn kết thúc.

Bằng cách tạo cặp hàm này, bạn có thể có bất kỳ lệnh tùy ý nào bạn muốn chạy trước và sau bất kỳ lệnh nào được đưa ra tại dấu nhắc. Bạn có thể sử dụng điều này để ghi nhật ký sử dụng shell, tạo khóa, kiểm tra môi trường hoặc như trong ví dụ của bạn tính thời gian hoặc tài nguyên đã sử dụng trong khi lệnh chạy.

Trong ví dụ này, chúng tôi sẽ tạo cho mình một dấu thời gian chuẩn trước khi chạy lệnh bằng cách sử dụng preexec()sau đó tính toán thời gian thực hiện lệnh bằng cách sử dụng precmd()và xuất nó trước dấu nhắc hoặc đăng xuất nó đi. Thí dụ:

preexec() {
   CMDSTART=$(date +%s%N)
}
precmd() {
   CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
   echo "Last command ran for $CMDRUNTIME nanoseconds."
}

Lưu ý: Đối với ví dụ cụ thể này, có một hàm dựng sẵn dễ dàng hơn. Tất cả bạn phải làm là bật báo cáo thời gian chạy trong ZSH và nó sẽ tự động làm điều này.

$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d  0.00s user 0.00s system 0% cpu 0.002 total

Trong một triển khai thực tế hơn preexec(), tôi sử dụng nó để xem shell đang chạy bên trong tmuxhay screen, và nếu vậy, để gửi thông tin về lệnh đang chạy ngược dòng sẽ được hiển thị trong tên tab.

Thật không may trong bash cơ chế nhỏ này không tồn tại. Đây là nỗ lực của một người để nhân rộng nó . Cũng xem câu trả lời của Gilles cho hack nhỏ tiện lợi tương tự.




muốn điều này có sẵn trong bash!
warren

Xem các liên kết của Gilles và những người khác, nó có thể được thực hiện trong bash với một chút khó khăn. Một lần nữa, tại sao bạn không chạy zsh? Đó là một vỏ rocking với nhiều lý do tốt để chuyển đổi hơn chỉ này!
Caleb

2
Nếu bạn đang sử dụng zsh, có một cách tốt hơn để làm điều đó. Biến môi trường BÁO CÁO khi được đặt sẽ xuất thông tin về thời gian thực hiện (như thể bạn đã chạy lệnh với 'thời gian' trước nó) cho bất kỳ lệnh nào mất nhiều hơn $ BÁO CÁO TỪ giây. Chỉ cần đặt thành 0 và nó sẽ cho bạn biết thời gian cho mỗi lệnh, với sự cố người dùng / sys để khởi động.
Joseph Garvin

1

Cách dễ nhất có lẽ sẽ được thiết lập PROMPT_COMMAND. Xem các biến Bash :

PROMPT_COMMAND
Nếu được đặt, giá trị được hiểu là lệnh thực thi trước khi in mỗi dấu nhắc chính ( $PS1).

Ví dụ: để tránh ghi đè bất kỳ lệnh nhắc hiện có nào, bạn có thể làm:

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"

không biết về điều đó - có vẻ như là một khởi đầu tốt, @cjm
warren

1
Đó là một sự khởi đầu, nhưng không giải quyết được vấn đề nhận biết khi nào một lệnh được chạy. Dấu nhắc có thể được rút ra vài phút hoặc vài giờ hoặc vài ngày trước khi một lệnh được gõ và chạy.
Caleb

0

csh/ tcshcó sự hỗ trợ tốt nhất cho tính năng này (và luôn có nó).

  The `time` shell variable can be set to execute the time builtin  command
  after the completion of any process that takes more than a given number
  of CPU seconds.

Nói cách khác, set time=1sẽ in ra thời gian đã sử dụng (hệ thống, người dùng, đã trôi qua) bằng bất kỳ lệnh nào mất hơn 1 giây thời gian cpu. Plain set timesẽ cho phép in ra thời gian cho tất cả các lệnh.

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.