Использование реализации grep
, которая знает флаг -o
иtr
:
#!/bin/sh
printf '%s\n' "$@" | grep -oiE '[0-9]+[^0-9]*booklets' | tr -dc '0-9\n'
Это sh
скрипт (, а не bash
, хотя он будет работать и с bash
). Он предполагает, что ни одна строка, переданная ему в командной строке, не содержит встроенного в нее символа новой строки.
Расширенное регулярное выражение [0-9]+[^0-9]*booklets
будет соответствовать любой строке, похожей на <integer><zero or more non-digit characters><"booklets">
, а с -o
это именно то, что будет возвращено из grep
. tr
просто удаляет из вывода grep
все, что не является цифрой или новой строкой.
tr
можно заменить на sed 's/[^0-9].*//'
, что удалит все, начиная с первого нецифрового символа -в строке.
Проверка:
$ sh script.sh 101s18-exam02--100-booklets.pdf
100
$ sh script.sh "MATH232 Exam 01 99 booklets.pdf"
99
$ sh script.sh 35BOOKLETS.pdf
35
$ sh script.sh 101s18-exam02--100-booklets.pdf "MATH232 Exam 01 99 booklets.pdf" 35BOOKLETS.pdf
100
99
35
Обратите внимание, что строки с пробелами необходимо заключать в кавычки.
Анализ журналов, созданных sudo strace -ff -p $(pidof containerd) -o strace_log
, показывает, что он останавливается, когда execve()
вызывается пользователем. процесс с именем runc init
. Это привело меня к этому отчету об ошибке в runc GH. страница , что объясняет, что это ошибка ядра, которая может воспроизводиться с каждым программа, которая использует pthreads и execve()
и представляет собой краткий Go программа, с помощью которой можно воспроизвести проблему:
package main
import (
"os"
"syscall"
)
func main() {
syscall.Exec("/bin/echo", []string{"/bin/echo", "Hello"}, os.Environ())
}
Зная, что это ошибка ядра, я использовал Raspberry Pi для тестирования. мог бы быстро собрать и заменить ядро Linux, не рискуя основная машина не загружается или играет с виртуальными машинами, а также Go не установлен по умолчанию в Raspbian. Я использовал следующий C программа для тестирования:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
void *foo(void *p)
{
(void) p;
while(1)
{
puts("in thread");
sleep(2);
}
}
int main(void)
{
printf("pid: %jd\n", (intmax_t) getpid());
pthread_t tid;
pthread_create(&tid, NULL, foo, NULL);
char *envp[] = {"var"};
char *ls_args[] = { "/bin/ls", "-l", NULL};
if (execve(ls_args[0], ls_args, envp) < 0) {
perror("execve error");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Постройте с помощью gcc strace-test.c -o strace-test -pthread
и убедитесь, что strace -f./strace-test
также застревает.
Патч, который должен был исправить strace, отправлен в ядро Linux. список рассылки в 2016 но он не был принят, вы можете прочитать всю дискуссию до понять, почему. Тем не менее, я применил этот патч к своему локальному Дерево ядра Linux для Raspberry Pi против rpi -5.6.y ветвь и после пересборки и замены ядра на Raspberry Pi strace -f./strace-test
больше не зависает. Исходный код Linux имеет немного изменилось с 2016 года, и патч не применяется чисто. ПСВ, полный патч, который я применил,:
diff --git a/kernel/fork.c b/kernel/fork.c
index 60a1295..c26aaa1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1224,7 +1224,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
struct mm_struct *mm;
int err;
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+ err = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
if (err)
return ERR_PTR(err);
diff --git a/kernel/signal.c b/kernel/signal.c
index 9ad8dea..ea7c7b5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -108,6 +108,10 @@ static bool sig_ignored(struct task_struct *t, int sig, bool force)
if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
return false;
+ /* Do not ignore signals sent from child to the parent */
+ if (current->ptrace && current->parent == t)
+ return 0;
+
/*
* Tracers may want to know about even ignored signal unless it
* is SIGKILL which can't be reported anyway but can be ignored