Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect the launching of programs on Linux?

Tags:

c

linux

pid

I wrote a simple daemon. This daemon should respond when I run any program. How to do this? In a big daemon loop:

while(1) {    /* function which catches new programm running */ } 

What functions to call in linux, when i'm running a new program (create new process)?

like image 856
nub Avatar asked May 20 '11 16:05

nub


People also ask

How do I see which programs are running on Linux?

To list currently running processes, use the ps , top , htop , and atop Linux commands. You can also combine the ps command with the pgrep command to identify individual processes.

How do I find the PID of a running process in Linux?

The easiest way to find out if process is running is run ps aux command and grep process name. If you got output along with process name/pid, your process is running.

How do I see what processes are running in Unix?

Open the terminal window on Unix. For remote Unix server use the ssh command for log in purpose. Type the ps aux command to see all running process in Unix. Alternatively, you can issue the top command to view running process in Unix.

How do I see what background processes are running on Linux?

The jobs command will show any background jobs started within the current shell, usually by starting a background task with the & operator or ^Z bg (e.g. sleep 10 & ). If you want to see all of the background processes running on the system, you can use ps -e , or ps -eF to get some additional details.


1 Answers

For Linux, there appears to be an interface in the kernel. Whilst researching this problem I came across people using CONFIG_CONNECTOR and CONFIG_PROC_EVENTS kernel configuration to get events on process death.

Some more google and I found this:

http://netsplit.com/2011/02/09/the-proc-connector-and-socket-filters/

The Proc Connector and Socket Filters Posted on February 9, 2011 by scott

The proc connector is one of those interesting kernel features that most people rarely come across, and even more rarely find documentation on. Likewise the socket filter. This is a shame, because they’re both really quite useful interfaces that might serve a variety of purposes if they were better documented.

The proc connector allows you to receive notification of process events such fork and exec calls, as well as changes to a process’s uid, gid or sid (session id). These are provided through a socket-based interface by reading instances of struct proc_event defined in the kernel header....

The header of interest is:

#include <linux/cn_proc.h> 

I found example code here:

http://bewareofgeek.livejournal.com/2945.html

/* This file is licensed under the GPL v2 (http://www.gnu.org/licenses/gpl2.txt) (some parts was originally borrowed from proc events example)  pmon.c  code highlighted with GNU source-highlight 3.1 */  #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>  /* * connect to netlink * returns netlink socket, or -1 on error */ 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; }  /* * subscribe on proc events (process notifications) */ 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; }  /* * handle a single process event */ static volatile bool need_exit = false; 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(int unused) { need_exit = true; }  int main(int argc, const char *argv[]) { 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); } 

I found that this code needs to run as root to get the notifications.

like image 116
David Crookes Avatar answered Oct 02 '22 18:10

David Crookes