taskset locks a command, or an already-running process, onto specific CPUs, and getting the mask wrong just means it runs nowhere at all. This covers launching a fresh command pinned to chosen CPUs, inspecting and changing an existing process, and rolling back cleanly when you are done. The examples use the installed taskset executable from util-linux 2.42.4. The local manpage on this system is labelled util-linux 2.39.3, but the options and behaviour used here are present in both references.
Allow about ten minutes. You need a shell and a Linux system with util-linux installed. Ordinary inspection and child-process examples do not need sudo. Changing another user's process requires the CAP_SYS_NICE capability, usually obtained through an appropriate administrative method.
Confirm which executable is first in your PATH, then print your current shell's affinity. Both are read-only checks:
$ command -v taskset
/home/linuxbrew/.linuxbrew/bin/taskset
$ taskset --version
taskset from util-linux 2.42.4
$ taskset -pc $$
pid 2030033's current affinity list: 0-7
Your path, PID and CPU range will differ. That list is the set of CPUs available to this process, not necessarily every CPU physically installed. If a service is already restricted by a container or cgroup, taskset cannot escape that restriction.
Checkpoint: Keep the reported list nearby. A CPU number absent from it can be rejected even if the host genuinely has a CPU with that number.
By default, taskset expects a hexadecimal bitmask. The lowest bit is logical CPU 0, so 0x1 selects CPU 0 and 0x3 selects CPUs 0 and 1. Compact, but easy to misread.
Use --cpu-list, or its short form -c, when the intended CPUs read better as numbers. Ranges and strides both work, so 0-6:2 means CPUs 0, 2, 4 and 6. For an existing PID, combine -p and -c as -pc; the long --cpu-list form is for launching a new command, not for changing an existing PID.
Run a child shell on CPU 0 and have it report its own affinity:
$ taskset --cpu-list 0 sh -c 'taskset -pc $$'
pid 2030043's current affinity list: 0
Whatever comes after the mask or list is the program to launch; everything past that belongs to that program. Here the outer taskset starts sh, and the inner command inspects the shell's own PID. The child exits when the check finishes, so this does not alter your current shell or any service.
To launch a real workload, replace /path/to/program and its arguments:
$ taskset --cpu-list 2,4-5 /path/to/program --input /path/to/input
Use a CPU list that showed up in your earlier check. For a long-running service, test it under the service account first and keep the existing service command available for rollback. Pinning a process can reduce the scheduler's freedom and make things worse, especially when the process needs several busy CPUs or shares data with other threads.
Use -p with a PID to retrieve its current affinity. You can inspect a process owned by another user without elevated privileges:
$ taskset -p PID
pid PID's current affinity mask: 3
Replace PID with decimal digits from a trusted process listing. The default output is a mask; ask for a list when that reads easier:
$ taskset -pc PID
pid PID's current affinity list: 0-1
A successful read only means the PID exists. It does not mean the process is currently running on every CPU shown, only that the scheduler may run its threads there.
This creates a disposable process, records its original setting, changes it, verifies the change, then removes the test process. It is an ordinary-user operation because the process belongs to you:
$ sleep 300 &
$ pid=$!
$ taskset -pc "$pid"
pid 2040000's current affinity list: 0-7
$ taskset -pc 0 "$pid"
pid 2040000's current affinity list: 0-7
pid 2040000's new affinity list: 0
$ taskset -pc "$pid"
pid 2040000's current affinity list: 0
$ kill "$pid"
$ wait "$pid" 2>/dev/null || true
The PID and original range here are examples. For a real process, save the original list before changing it, then restore that same list with taskset -pc ORIGINAL_LIST PID. If you did not save it, retrieve the current value before making another change rather than guessing. The affinity change is not persistent configuration, but it stays in force for the process and its threads until changed again or the process exits.
Warning: Do not experiment on a critical service, PID 1, or a kernel thread. An affinity naming no legal CPU fails with an error. A successful command only means the kernel accepted the affinity; it does not guarantee immediate migration to a selected CPU.
Linux schedules threads, and a PID can have several. By default, taskset -p acts on just the specified task. Add -a to retrieve or set the affinity of all tasks, meaning every thread under that PID:
$ taskset -apc PID
pid PID's current affinity list: 0-7
Use -a deliberately. Restricting only one thread can produce a result that disagrees with the rest of a multithreaded program, while restricting every thread can create a bottleneck. Check the program's threading model before choosing either way.
You can always change a process belonging to your own user. Changing another user's process needs CAP_SYS_NICE. Retrieval is allowed for any process, so try the read-only check before reaching for sudo. If the command reports permission denied, use the normal administrative path for that host and confirm the change is authorised.