Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: bash возвращает неверное значение переменной/bash returns wrong var value  (Прочитано 2587 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
Погуглил заранее, поискал сейчас по форуму, пообщался с компетентным товарищем -- не помогло-с.
Есть простая процедура/функция, ищущая среди процессов уже запущенные копии, и считающая их.
Если первой строкой указан интерпретатор, то из переменной возвращается неверное значение, если интерпретатор не указан -- всё нормально.
CHECKPROC()
{
i=`ps ax | grep -c "$0"`
#i=$(ps ax | grep -c $0 ) дает тот же результат
ps ax | grep -c $0
echo variable is $i
}
CHECKPROCK
Нет в первой строчке указания на интерпретатор -- возвращает всё как положено
2
variable is 2
Первой строчкой идёт #!/bin/bash или #!/bin/sh
2
variable is 3

Баш 4.3.11, товарищ запускал на 5.1.16 и 4.4.20.
Куды смотреть, что неправильно делаю?

АП0. Оно не меняет оболочку?
При вписанном #!/bin/sh первой строкой без пробелов запуск echo $SHELL из скрипта возвращает /bin/bash
...меняет, через процессы видно, SHELL -- переменная окружения.

АП1.
В ответ на сообщения valrust об особенностях запуска скрипта с shebang и без него.
Только сейчас догнал, почему греп возвращает сам себя без shebang.
Действительно в списке процессов запускается bash без параметров.
И т.о. логично, что pgrep -c $0 возвращает 0 при любом количестве запущенных процессов, зато количество bash растёт.

Решение задачи "проверить, не работают ли другие копии скрипта" более надежно решаются через lsof -R /path/to/script.sh
« Последнее редактирование: 16 Января 2022, 12:42:27 от DarkArchangel »
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
навскидку лишний перенос
CHECKPROC() {
i=`ps ax | grep -c "$0"`
#i=$(ps ax | grep -c $0 ) дает тот же результат
ps ax | grep -c $0
echo variable is $i
}
CHECKPROC

« Последнее редактирование: 15 Января 2022, 21:53:12 от ALiEN175 »
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
Не, с открывающей фигурной скобкой на одной линии с именем функции тот же результат отдаёт
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
Хм, возможно,
ps ax | grep -c "$0"
Даёт +1 лишний из-за того, что сам grep попадает в результат и взаимодействует с функцией.

Пробуйте
CHECKPROC() {
i=$(pgrep -c $0)
pgrep -c $0
echo variable is $i
}
CHECKPROC
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
Оно в обоих случаях даёт один лишний каунт и в обоих случаях должно возвращать одинаковое значение.
ап.
pgrep возвращает по нулям, хотя по логике должен, наверное, по единице?
Но да, в этом случае одинаково
« Последнее редактирование: 15 Января 2022, 22:16:54 от DarkArchangel »
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
DarkArchangel, как-то так:

$: cat ./fortest               
#!/bin/bash
CHECKPROC() {
i=`ps ax | grep $0`
ps ax | grep $0

printf "\n\nIn variable:\n$i"

}
CHECKPROC

$: ./fortest   
   7725 pts/0    S+     0:00 /bin/bash ./fortest
   7735 pts/0    S+     0:00 grep ./fortest


In variable:
   7725 pts/0    S+     0:00 /bin/bash ./fortest
   7727 pts/0    S+     0:00 /bin/bash ./fortest
   7729 pts/0    S+     0:00 grep ./fortest% 
Надо разбираться, откуда в переменной еще один процесс.
« Последнее редактирование: 15 Января 2022, 22:38:41 от ALiEN175 »
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
Есть вариант, что при вызове команды через $(...) вызывается саб-шелл (апострофы работают так же?), однако тогда почему без указания интерпретатора оно работает как положено -- всё равно пока непонятно.
В общем если что-то ещё накопается -- отпишусь в ветке и поправлю стартовое сообщение. Не появится мыслей ни у меня, ни у остальных -- отправлюсь уже на профильные ресурсы. Мелочь, конечно, а жизнь на ровном месте может подпортить.

И да, спасибо за мнение и возможное направление для покопать
« Последнее редактирование: 15 Января 2022, 22:51:31 от DarkArchangel »
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
у меня и без шебанга так же двоится:
i=`ps ax | grep $0`
printf "$i"
C шебангом !/bin/bash
$: ./fortest     
   8289 pts/0    S+     0:00 /bin/bash ./fortest
   8291 pts/0    S+     0:00 /bin/bash ./fortest
   8293 pts/0    S+     0:00 grep ./fortest% 

Без него
$: ./fortest     
   8334 pts/0    S+     0:00 sh ./fortest
   8336 pts/0    S+     0:00 sh ./fortest
   8338 pts/0    S+     0:00 grep ./fortest%     
     
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
Рабочее решение c pgrep
#!/bin/bash
CHECKPROC() {
PROC=$(basename $0)
i=$(pgrep -c $PROC)
pgrep -c $PROC
echo variable is $i
}
CHECKPROC
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
Возможно, виноват конвейер
$: cat ./fortest
#!/bin/bash
CHECKPROC() {
PROC=$(basename $0)
i=$(pgrep -c $PROC)
pgrep -c $PROC
echo variable is $i
}
CHECKPROC

$: ./fortest   
1
variable is 1

$: cat ./fortest
#!/bin/bash
CHECKPROC() {
PROC=$(basename $0)
i=$(pgrep -c $PROC | cat) # <----- КОНВЕЙЕР!
pgrep -c $PROC | cat # <----- А тут ни на что не влияет.
echo variable is $i
}
CHECKPROC

$: ./fortest   
1
variable is 2


« Последнее редактирование: 15 Января 2022, 23:20:14 от ALiEN175 »
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
Сейчас интереса ради добавил в скрипт sleep 10, запустил несколько копий с nohup.
В соседнем терминале пробовал делать pgrep -c script_name.sh -- всегда 0 возвращает
ps aux | grep -c script_name.sh -- всегда возвращает сколько запущено + 1 процесс на сам grep
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн valrust

  • Активист
  • *
  • Сообщений: 364
    • Просмотр профиля
Допустим в bash хотим запустить на исполнение такой скрипт (файлу назначены права исполнения)
./script
Bash будет действовать по такому алгоритму:
  • Bash с помощью системного вызова clone (fork) создаст собственную копию (дочерний процесс). Родительский процесс будет ожидать завершение дочернего процесса.
    Дочерний процесс в списке процессов будет отображаться как bash.
  • В дочернем процессе с помощью системного вызова execve будет выполнена попытка загрузить исполняемый код из файла ./script и начать его выполнение.
  • Если в скрипте есть shebang (первая строка в формате #!/bin/bash), то ядро Linux выполнит системный вызов execve и в дочерний процесс загрузит код исполняемого файла /bin/bash, а в качестве первого аргумента будет указана строка "./script".
    Дочерний процесс в списке процессов будет отображаться как /bin/bash ./script
  • Если же в скрипте не указан shebang, то системный вызов execve вернет ошибку "ENOEXEC (Ошибка формата выполняемого файла)" и тогда bash в дочернем процессе откроет файл ./script на чтение и начнет его выполнение.
    Дочерний процесс в списке процессов будет отображаться как bash.

Так как подсчет количества процессов строится на поиске в списке процессов строки с названием скрипта, то результаты будут разные в зависимости от того указан shebang или нет.

Оффлайн DarkArchangel

  • Автор темы
  • Участник
  • *
  • Сообщений: 126
    • Просмотр профиля
всегда 0 возвращает
???





Пользователь добавил сообщение 16 Января 2022, 09:39:44:
Цитировать
Так как подсчет количества процессов строится на поиске в списке процессов строки с названием скрипта, то результаты будут разные в зависимости от того указан shebang или нет.
С shebang и без shebang разные -- только половина вопроса. Должно же возвращать всегда одинаковую пару символов, а не X/X в одном случае и x/X+1 в другом

Пользователь добавил сообщение 16 Января 2022, 09:41:42:
Добавил таск на лаунчпаде до кучи, подтвердится/нет -- не знаю.
таска

Пользователь добавил сообщение 16 Января 2022, 11:46:41:
valrust
Только сейчас догнал, почему греп возвращает сам себя без shebang.
Действительно в списке процессов запускается bash без параметров.
И т.о. логично, что pgrep -c $0 возвращает 0 при любом количестве запущенных процессов, зато количество bash растёт.
« Последнее редактирование: 16 Января 2022, 16:05:16 от ALiEN175 »
asus p8h67/intel xeon e3-1230v2+Scythe Mugen/8GB PC12600/AMD Radeon 6770, open-source driver/2tb Hitachi deskstar 7200 rpm + Goodram Iridium 120G, Lubuntu 22.04

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6754
  • 20% Cooler
    • Просмотр профиля
Внимательнее:
pgrep -c $(basename $0)
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

 

Страница сгенерирована за 0.037 секунд. Запросов: 25.