unshare --pid /bin/bash - fork cannot allocate memory - linux

I'm experimenting with linux namespaces. Specifically the pid namespace.
I thought I'd test something out with bash but run into this problem:
unshare -p /bin/bash
bash: fork: Cannot allocate memory
Running ls from there gave a core dump. Exit is the only thing possible.
Why is it doing that?

The error is caused by the PID 1 process exits in the new namespace.
After bash start to run, bash will fork several new sub-processes to do somethings. If you run unshare without -f, bash will have the same pid as the current "unshare" process. The current "unshare" process call the unshare systemcall, create a new pid namespace, but the current "unshare" process is not in the new pid namespace. It is the desired behavior of linux kernel: process A creates a new namespace, the process A itself won't be put into the new namespace, only the sub-processes of process A will be put into the new namespace. So when you run:
unshare -p /bin/bash
The unshare process will exec /bin/bash, and /bin/bash forks several sub-processes, the first sub-process of bash will become PID 1 of the new namespace, and the subprocess will exit after it completes its job. So the PID 1 of the new namespace exits.
The PID 1 process has a special function: it should become all the orphan processes' parent process. If PID 1 process in the root namespace exits, kernel will panic. If PID 1 process in a sub namespace exits, linux kernel will call the disable_pid_allocation function, which will clean the PIDNS_HASH_ADDING flag in that namespace. When linux kernel create a new process, kernel will call alloc_pid function to allocate a PID in a namespace, and if the PIDNS_HASH_ADDING flag is not set, alloc_pid function will return a -ENOMEM error. That's why you got the "Cannot allocate memory" error.
You can resolve this issue by use the '-f' option:
unshare -fp /bin/bash
If you run unshare with '-f' option, unshare will fork a new process after it create the new pid namespace. And run /bin/bash in the new process. The new process will be the pid 1 of the new pid namespace. Then bash will also fork several sub-processes to do some jobs. As bash itself is the pid 1 of the new pid namespace, its sub-processes can exit without any problem.

This does not explain why this happens, but shows how to correctly launch a shell in a new pid namespace:
Use the -f flag to fork off the shell from unshare, so that the new shell gets PID 1 in the newly created namespace:
unshare -fp /bin/bash
You probably also want to pass the --mount-proc option, so that your ps listing reflects your newly created PID namespace rather than the parent PID namespace:
unshare -fp --mount-proc /bin/bash
Now run ps:
# ps
PID TTY TIME CMD
1 pts/1 00:00:00 bash
11 pts/1 00:00:00 ps

Related

How to monitor process status during process lifetime

I need to track the process status ps axf during executable lifetime.
Let's say I have executable main.exec and want to store into a file all subprocess which are called during main.exec execution.
$ main.exec &
$ echo $! # and redirect every ps change for PID $! in a file.
strace - trace system calls and signals
$ main.exec &
$ strace -f -p $! -o child.txt
-f Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls. Note that -p PID -f will attach all threads of process PID if it is multi-threaded, not only thread with thread_id = PID.
If you can't recompile and instrument main.exec, ps in a loop is a simple option that may work for you:
while true; do ps --ppid=<pid> --pid=<pid> -o pid,ppid,%cpu,... >> mytrace.txt; sleep 0.2; done
Then parse the output accordingly.
top may also work, and can run in batch mode but not sure if you can get it to dynamically monitor child processes like ps. Don't think so.

Bash script dd and fsck not killed

I need to remove a lv which is under use from a script which is doing a dd, fcsk and some more tasks on some peer node.so am just killing the script and trying to remove the lv from that peer, but it seems not working with error open lvs.
but for the same case if i kill the dd then removing the lv its working fine.
may be am asking a silly question but need to know why so??
If you kill your script sending SIGTERM or SIGKILL to its PID, normally you would send the signal only to the parent process. dd is running in a child process which won't receive the signal. Once the parent is killed, the child is inherited by init and it will keep on running.
To send the signal to the whole process group use:
kill -- -PID
or
kill -9 -PID
where PID is the PID of your script. Note the minus sign prepended to PID.
From man kill
-n where n is larger than 1. All processes in process group n are signaled.
Example
I am running dd from a shell script:
PID TGID TID PGID PPID COMMAND
5828 5828 5828 5828 20127 sh
5829 5829 5829 5828 5828 dd
The Process Group ID (PGID) is the PID of the parent (5828).
If I run the following command:
kill -9 5828
I obtain the following situation:
PID TGID TID PGID PPID COMMAND
5829 5829 5829 5828 1 dd
dd is still running and it has been inherited by init (PPID is 1).
If instead I run:
kill -9 -5828
both the script and dd are killed.
EDIT: The process you want to kill is launched remotely via ssh.
Having ssh launch dd/fsck remotely changes everything. A simple but not recommended solution could be the following.
A script launches dd/fsck remotely via ssh in the background and gets the PID.
remote_pid=$(ssh user#host 'dd if=/dev/urandom of=/dev/zero & echo $!')
Then the script must not return and trap your signal. Your handler opens a new ssh connection and signals remote_pid.
Cleaning up in a second ssh connection is not recommended, as it could fail and leave a lot of mess behind.
For a more advanced solution please see https://unix.stackexchange.com/questions/40023/get-ssh-to-forward-signals

bash - get io statistics of the child process

I have a bash process which calls another child process (mysqldump) for example. I need to determine the io usage of this child process. I tried cat /proc/self/io but values for io are connected only with the parent process. But I need the data for the child process. I can determine the pid of the child process and try view /proc/[pid of child]/io but when should I do that? If I do mysqldump and then /proc/[pid of child]/ioŠ± /proc/[pid of child] won't exist after the finishing of the child process. Thanks!
You can probably use strace command as below to get that result.
strace -e trace=read,write -o ls.log ls
Here, strace will give the result for ls command. If you want to attach to particular process, use the -p pid option like
strace -e trace=read,write -o ls.log -p <child process PID>
More about Strace Command Here

Child process to kill its parent whithout terminating itself

How can I kill parent process script from child process script, without terminating child process in Linux.
If your shell defines PPID, kill $PPID will kill the parent. If your shell does not define PPID, you can probably get it with PPID=$( ps -o ppid= $$ ). There is no reason for this action to kill the child.

How to run a program and know its PID in Linux?

How to run a program and know its PID in Linux?
If I have several shells running each other, will they all have separate PIDs?
Greg's wiki to the rescue:
$! is the PID of the last backgrounded process.
kill -0 $PID checks whether $PID is still running. Only use this for processes started by the current process or its descendants, otherwise the PID could have been recycled.
wait waits for all children to exit before continuing.
Actually, just read the link - It's all there (and more).
$$ is the PID of the current shell.
And yes, each shell will have its own PID (unless it's some homebrewed shell which doesn't fork to create a "new" shell).
1) There is a variable for that, often $$:
edd#max:~$ echo $$ # shell itself
20559
edd#max:~$ bash -c 'echo $$' # new shell with different PID
19284
edd#max:~$ bash -c 'echo $$' # dito
19382
edd#max:~$
2) Yes they do, the OS / kernel does that for you.
the top command in linux(Ubuntu) shows the memory usage of all running programs in linux with their pid. Kill pid can kill the process.

Resources