Как определить, открыт ли файл в bash-скрипте на FreeBSD - PullRequest
0 голосов
/ 18 февраля 2019

Я пытаюсь перенести сценарий Linux bash на FreeBSD.Сценарий должен проверить, открыт ли файл (для записи), прежде чем решить, следует ли предпринять какое-либо действие.

В Linux это было легко с помощью команды fuser:

if [[ ! `/usr/bin/fuser "$FILE"` ]]
     then
     ...
fi

Однако во FreeBSD команда fuser кажется полностью неработающей (подтверждается this ) и не возвращает никаких правильных кодов выхода или действительно полезных выходных данных для stdout.Например, для файла, который активно записывается в:

# fuser file 
file:

Редактировать:


Комментарий Владимира Ботки:

«Показывает простой тест во FreeBSD 12.0»:

# tail -f /scratch/test-file`
# fuser /scratch/test-file
/scratch/test-file: 45042
# echo $?
0
# ps ax | grep 45042
45042  0  I+       0:00.00 tail -f /scratch/test-file
45232  1  R+       0:00.00 grep 45042

На моем компьютере с FreeBSD (также FreeBSD 12) этот же тест дает следующее:

# tail -f /scratch/test-file
# fuser /scratch/test-file
/scratch/test-file:
# echo $?
0

Комментарий Владимира Ботки:

Давайте попробуем проверить запись в файл с помощью простой программы на C, которая открывает файл, ожидает ввода и записывает ввод в файл.

Вот мой тест на скомпилированном коде C:

# ./a.out
Enter num:

# fuser /scratch/test-file
/scratch/test-file:
# echo $?
0

Следовательно, fuser, похоже, не работает.Тем не менее, он кажется только сломанным в моей системе, а не в системе Владимира Ботки, что странно, поскольку они оба FreeBSD 12.


Кажется, я мог бы использовать lsof или fstat, чтобы получитьэта информация, но не без какого-либо сложного анализа выходных данных, что сделает мой сценарий более сложным.Я задавался вопросом, может ли кто-нибудь указать мне на простую команду «да / нет», чтобы определить, используется ли файл, такой как fuser, который будет работать во FreeBSD?

Большое спасибо,

Ответы [ 4 ]

0 голосов
/ 28 февраля 2019

То, что вы назвали «сломанным», также может быть правильным поведением в зависимости от привилегий владельца процесса.

Вы сможете видеть свои собственные процессы только через fuser, если у вас нет root илиэквивалентные привилегии и могли видеть процессы других пользователей.Убедитесь, что вы используете оба сеанса от имени одного и того же пользователя root.

0 голосов
/ 19 февраля 2019

Если fuser не работает в вашей системе и если все в порядке, выполните анализ, например, при попытке открыть файл fstat:

$ cat > /tmp/test

Это выводиз fstat /tmp/test:

# fstat /tmp/text
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME
root     cat        39590    1 [restricted]   3812 -rw-r--r--       0  w  /tmp/text

Если файл не используется, вы получите только заголовки:

# fstat /tmp/text
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME

Итак, вы можете использовать что-то вроде:

[ `fstat /tmp/test | wc -l` -gt 1 ] && echo "in use"

или

test `fstat /tmp/test | wc -l` -gt 1 && echo "in use"
0 голосов
/ 22 февраля 2019

Я заключаю, что fuser не работает в FreeBSD.В конце я решил разобрать вывод fstat, чтобы решить проблему.fstat производит следующий вывод для файла, который активно записывается (и есть еще один процесс, читающий его, отсюда две строки):

# fstat file 
USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W NAME
root     smbd       36299   41 /data    1282756 -rwxr--r--  7407140864 rw  file
root     smbd       36295   30 /data    1282756 -rwxr--r--  7407140864  r  file

Следующий код bash проверяет файл, используя fstat, удаляет строку заголовка (sed), затем использует awk для захвата 9-го столбца, который касается того, открыт ли файл для чтения или записи.Затем следует grep для поиска флага записи w в любой из строк.Если он найдет один, он вернет истину.Все условие отменяется (!), чтобы гарантировать, что действие выполняется только в том случае, если файл НЕ используется:

 if [[ ! `/usr/bin/fstat "$FILE" | sed 1d | awk '{print $9}' | grep "w"` ]]
 then
    ... do something ...
 fi
0 голосов
/ 19 февраля 2019

Ваша заявка

"во FreeBSD команда fuser кажется полностью неработающей"

относится к Сведения о порте: утилита fuser POSIX fuser для FreeBSD срок действия которого устарел и срок его действия истек: 2012-11-26

Давайте попробуем этот простой тест во FreeBSD 12.0.Откройте терминал и запустите

# touch /scratch/test-file
# tail -f /scratch/test-file

Keep tail в ожидании содержимого test-file .Откройте второй терминал и запустите

# fuser /scratch/test-file
/scratch/test-file: 45042
# echo $?
0
# ps ax | grep 45042
45042  0  I+       0:00.00 tail -f /scratch/test-file
45232  1  R+       0:00.00 grep 45042

Давайте попробуем проверить запись в файл с помощью простой программы на C, которая открывает файл, ожидает ввода и записывает ввод в файл.

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int num;
   FILE *fptr;
   fptr = fopen("/scratch/test-file","w");
   printf("Enter num: ");
   scanf("%d",&num);
   fprintf(fptr,"%d",num);
   fclose(fptr);
   return 0;
}

# ./a.out 
Enter num: 

Держите программу в ожидании ввода.Откройте третий терминал и запустите

# fuser /scratch/test-file
/scratch/test-file: 45448w 45042
# echo $?
0
# ps ax | grep 45448
45448  0  I+       0:00.00 ./a.out
45464  1  S+       0:00.00 grep 45448

Если файл открыт для записи fuser добавляет «w» к PID и сообщает

w ...Файл открыт для записи.

Простой скрипт bash

#!/usr/local/bin/bash
my_file=/scratch/test-file
result=`fuser $my_file 2>&1`
pid=`echo $result | cut -d ':' -f 2-`
if [ -z "$pid" ]; then
    echo "$my_file is not opened by any process"
else
    echo "$my_file is opened by process PID(s): $pid"
fi

показывает

# ./test.bash
/scratch/test-file is opened by process PID(s): 45448w 45042

соответственно

# ./test.bash
/scratch/test-file is not opened by any process

Если этоне работает для вас см. Как создать минимальный, полный и проверяемый пример для предоставления подробностей.

...