Làm cách nào tôi có thể đăng nhập tất cả các quá trình khởi chạy trong Linux?


55

Tôi muốn có được một bản ghi của tất cả các quy trình được khởi chạy cùng với thời gian chúng được khởi chạy và các đối số mà chúng được đưa ra. Điều này có thể có trong Linux không?

Câu trả lời:


43

Điểm bắt đầu của bạn nên được kiểm toán.

Hãy thử một cái gì đó như thế này:

apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve

1
Tôi đang gặp lỗi The audit system is disabledTôi có thể kích hoạt nó ở đâu?
Tombart

1
cũng có thể giải quyết được một vấn đề chmod 0750 /sbin/audispdnhưng nó vẫn không hoạt động (Debian Wheezy)
Tombart

nói Unable to set audit pid, exitingnhưng tôi đoán rằng vấn đề thực sự sẽ là hệ thống đang chạy trong container LXC
Tombart

Làm thế nào để kiểm toán tích hợp với systemd journald? Làm chức năng của họ chồng chéo?
CMCDragonkai

Tôi đã thử điều này trên một máy chủ trực tiếp và tôi đã giết nó một cách hiệu quả, gần như không phản hồi. Tôi hầu như không quản lý để loại bỏ quy tắc này và làm cho máy chủ phản hồi lại
Shocker

10

Tôi cần phải làm điều này, ngoại trừ (1) Tôi không cần thời gian và (2) Tôi chỉ quan tâm đến các quy trình được bắt đầu bởi một quy trình nhất định, và con cái và hậu duệ của nó. Ngoài ra, trong môi trường tôi đang sử dụng, nó là không thể để có được auditdhoặc accton, nhưng đã có valgrind.

Tiền tố sau đây cho quá trình quan tâm trên dòng lệnh:

valgrind --trace-children=yes

Thông tin bạn cần sẽ có trong đầu ra nhật ký được hiển thị trên STDERR.


3
Theo mặc định, valgrind chạy với memcheckcông cụ. Để vô hiệu hóa công cụ và ghi nhật ký liên quan của nó và chỉ in việc tạo các lệnh mới (ngoài đầu ra thông thường của chương trình của bạn), hãy sử dụng lệnh sau thay thế : valgrind --tool=none --trace-children=yes [command and args here]. Bất cứ khi nào một quy trình con được sinh ra, Valgrind sau đó sẽ ghi lại toàn bộ lệnh, bao gồm cả các đối số được truyền cho nó.
Rob W

6

Bạn có thể sử dụng snoopy cho việc này.

Nó rất đơn giản để cài đặt, và vì 2.x nó có thể ghi dữ liệu tùy ý (đối số, biến môi trường, cwd, v.v.).

Tiết lộ: Người duy trì snoopy ở đây.


2

Bạn có thể chạy startmon và làm theo đầu ra tiêu chuẩn của nó, Ctrl-C khi hoàn tất. Dưới đây là cách biên dịch và chạy startmon trên các bản phát hành có nguồn gốc Red Hat gần đây (RHEL, Fedora, CentOS):

sudo yum install git cmake gcc-c++
git clone https://github.com/pturmel/startmon
cd startmon
cmake .
make
sudo ./startmon -e

Trên Debian (và Ubuntu, v.v.), dòng đầu tiên ở trên thay đổi thành:

sudo apt-get install git cmake g++

Ngoài ra, bạn có thể thử execsnooptập lệnh trong perf-tools, xem câu trả lời này . Theo mặc định, chỉ có 8 đối số đầu tiên được hiển thị (9 bao gồm tên chương trình); bạn có thể tăng điều này thông qua

sudo ./execsnoop -a 16

Nếu bạn không có quyền truy cập root vào hệ thống, điều tốt nhất bạn có thể làm là tiếp tục bỏ phiếu /procvà hy vọng nó sẽ nắm bắt mọi thứ (mà nó sẽ không), nhưng để hoàn thành đây là một kịch bản để làm điều đó (Tôi đã loại bỏ trùng lặp để đơn giản hóa đầu ra) Mặc dù điều này không tốt bằng việc theo dõi chúng đúng cách bằng một trong các phương pháp trên, nhưng nó có một lợi thế nhỏ là hiển thị rõ ràng các dấu phân cách giữa các đối số dòng lệnh, trong trường hợp bạn cần phải nói với sự khác biệt giữa các không gian bên trong một đối số và không gian giữa các đối số. Kịch bản này không hiệu quả vì nó sử dụng CPU (tốt, một trong những lõi của nó) 100% thời gian.

function pstail () { python -c 'import os
last=set(os.listdir("/proc")) ; o=x=""
while True:
 pids=set(os.listdir("/proc"))
 new=pids.difference(last);last=pids
 for n in new:
  try: o,x=x,[j for j in open("/proc/"+n+"/cmdline")
    .read().split(chr(0)) if j]
  except IOError: pass
  if x and not o==x: print n,x' ; }

pstail

Bạn cũng có thể vá execsnoopđể cho bạn biết rõ hơn đối số nào là:grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop


1

CONFIG_FTRACECONFIG_KPROBESthông quabrendangregg/perf-tools

git clone https://github.com/brendangregg/perf-tools.git
cd perf-tools
git checkout 98d42a2a1493d2d1c651a5c396e015d4f082eb20
sudo ./execsnoop

Trên một vỏ khác:

while true; do sleep 1; date; done

Shell đầu tiên hiển thị dữ liệu định dạng:

Tracing exec()s. Ctrl-C to end.                                                        
Instrumenting sys_execve                                                               
   PID   PPID ARGS 
 20109   4336 date                                                                                       
 20110   4336 sleep 1                                                                                    
 20111   4336 date                                                                                                                                                                                                 
 20112   4336 sleep 1                                                                                    
 20113   4336 date                                                                                       
 20114   4336 sleep 1                                                                                    
 20115   4336 date                                                                                       
 20116   4336 sleep 1

CONFIG_PROC_EVENTS

Phiên mẫu:

$ su
# ./proc_events &
# /proc_events.out &
set mcast listen ok
# sleep 2 & sleep 1 &
fork: parent tid=48 pid=48 -> child tid=56 pid=56
fork: parent tid=48 pid=48 -> child tid=57 pid=57
exec: tid=57 pid=57
exec: tid=56 pid=56
exit: tid=57 pid=57 exit_code=0
exit: tid=56 pid=56 exit_code=0

CONFIG_PROC_EVENTShiển thị các sự kiện cho người dùng thông qua một ổ cắm netlink .

Proc_events.c được điều chỉnh từ: https://bnterestofgeek.livejournal.com/2945.html

#define _XOPEN_SOURCE 700
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <signal.h>
#include <errno.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static volatile bool need_exit = false;

static int nl_connect()
{
    int rc;
    int nl_sock;
    struct sockaddr_nl sa_nl;

    nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
    if (nl_sock == -1) {
        perror("socket");
        return -1;
    }
    sa_nl.nl_family = AF_NETLINK;
    sa_nl.nl_groups = CN_IDX_PROC;
    sa_nl.nl_pid = getpid();
    rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
    if (rc == -1) {
        perror("bind");
        close(nl_sock);
        return -1;
    }
    return nl_sock;
}

static int set_proc_ev_listen(int nl_sock, bool enable)
{
    int rc;
    struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
        struct nlmsghdr nl_hdr;
        struct __attribute__ ((__packed__)) {
            struct cn_msg cn_msg;
            enum proc_cn_mcast_op cn_mcast;
        };
    } nlcn_msg;

    memset(&nlcn_msg, 0, sizeof(nlcn_msg));
    nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
    nlcn_msg.nl_hdr.nlmsg_pid = getpid();
    nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;

    nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
    nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
    nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);

    nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;

    rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
    if (rc == -1) {
        perror("netlink send");
        return -1;
    }

    return 0;
}

static int handle_proc_ev(int nl_sock)
{
    int rc;
    struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
        struct nlmsghdr nl_hdr;
        struct __attribute__ ((__packed__)) {
            struct cn_msg cn_msg;
            struct proc_event proc_ev;
        };
    } nlcn_msg;
    while (!need_exit) {
        rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
        if (rc == 0) {
            /* shutdown? */
            return 0;
        } else if (rc == -1) {
            if (errno == EINTR) continue;
            perror("netlink recv");
            return -1;
        }
        switch (nlcn_msg.proc_ev.what) {
            case PROC_EVENT_NONE:
                printf("set mcast listen ok\n");
                break;
            case PROC_EVENT_FORK:
                printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n",
                        nlcn_msg.proc_ev.event_data.fork.parent_pid,
                        nlcn_msg.proc_ev.event_data.fork.parent_tgid,
                        nlcn_msg.proc_ev.event_data.fork.child_pid,
                        nlcn_msg.proc_ev.event_data.fork.child_tgid);
                break;
            case PROC_EVENT_EXEC:
                printf("exec: tid=%d pid=%d\n",
                        nlcn_msg.proc_ev.event_data.exec.process_pid,
                        nlcn_msg.proc_ev.event_data.exec.process_tgid);
                break;
            case PROC_EVENT_UID:
                printf("uid change: tid=%d pid=%d from %d to %d\n",
                        nlcn_msg.proc_ev.event_data.id.process_pid,
                        nlcn_msg.proc_ev.event_data.id.process_tgid,
                        nlcn_msg.proc_ev.event_data.id.r.ruid,
                        nlcn_msg.proc_ev.event_data.id.e.euid);
                break;
            case PROC_EVENT_GID:
                printf("gid change: tid=%d pid=%d from %d to %d\n",
                        nlcn_msg.proc_ev.event_data.id.process_pid,
                        nlcn_msg.proc_ev.event_data.id.process_tgid,
                        nlcn_msg.proc_ev.event_data.id.r.rgid,
                        nlcn_msg.proc_ev.event_data.id.e.egid);
                break;
            case PROC_EVENT_EXIT:
                printf("exit: tid=%d pid=%d exit_code=%d\n",
                        nlcn_msg.proc_ev.event_data.exit.process_pid,
                        nlcn_msg.proc_ev.event_data.exit.process_tgid,
                        nlcn_msg.proc_ev.event_data.exit.exit_code);
                break;
            default:
                printf("unhandled proc event\n");
                break;
        }
    }

    return 0;
}

static void on_sigint(__attribute__ ((unused)) int unused)
{
    need_exit = true;
}

int main()
{
    int nl_sock;
    int rc = EXIT_SUCCESS;

    signal(SIGINT, &on_sigint);
    siginterrupt(SIGINT, true);
    nl_sock = nl_connect();
    if (nl_sock == -1)
        exit(EXIT_FAILURE);
    rc = set_proc_ev_listen(nl_sock, true);
    if (rc == -1) {
        rc = EXIT_FAILURE;
        goto out;
    }
    rc = handle_proc_ev(nl_sock);
    if (rc == -1) {
        rc = EXIT_FAILURE;
        goto out;
    }
    set_proc_ev_listen(nl_sock, false);
out:
    close(nl_sock);
    exit(rc);
}

GitHub upatream .

Tuy nhiên, tôi không nghĩ rằng bạn có thể nhận được dữ liệu xử lý như UID và xử lý các đối số vì exec_proc_eventchứa quá ít dữ liệu: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc .h # L80 Chúng tôi có thể cố gắng đọc nó ngay lập tức /proc, nhưng có một rủi ro là quá trình đã kết thúc và một quá trình khác đã thực hiện PID của nó, vì vậy nó sẽ không đáng tin cậy.

Đã thử nghiệm trong Ubuntu 17.10.


0

Ngoài ra, bạn có thể sử dụng trên đỉnh để xem sử dụng tài nguyên theo quy trình. Đây là công cụ hữu ích để ghi nhật ký và phân tích việc sử dụng tài nguyên trong từng phần của thời gian


-3

Bạn có thể thử cat ~/.bash_historysystem log viewer, điều này có thể giúp bạn ra ngoài.


1
~/.bash_historyRõ ràng chỉ chứa các lệnh tôi đã thực hiện trong một thiết bị đầu cuối. Tôi đang tìm kiếm nhật ký của tất cả các chương trình được thực hiện, ví dụ như khi tôi nhấp vào biểu tượng để mở ứng dụng email khách, gedit hoặc tôi mở trình duyệt của mình và trình duyệt của tôi tự thực hiện một quy trình khác. Câu trả lời của new123456 đã lừa.
runeks

1
Chúng ta cũng nói thêm rằng lệnh historylà cách thông thường để truy cập thông tin này.
bryn
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.