我需要使用 shell CGI 写入和读取配置文件,并且我还有一个 C 程序必须每隔几秒读取和修改配置文件。我尝试使用集群来维护数据完整性并防止竞争条件,但 CGI 和 C 程序仍然能够同时访问该文件。
如果我在文件上使用 2 个 C 程序,它可以工作,但不能同时使用 shell CGI 和 C 程序。
这是正在使用的C程序:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *file;
struct flock fl = {0};
char buff[1000];
file = fopen("/home/siddusuhaas/sample.conf", "r+");
if (file == NULL) {
perror("Error opening file");
return 1;
}
printf("Opened File\n");
// Set an exclusive lock on the entire file
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
if (fcntl(fileno(file), F_SETLKW, &fl) == -1) {
perror("Error locking file");
fclose(file);
return 1;
}
printf("File Lock Successful\n");
// Perform operations on the locked file here
system("lslocks | grep 'bcf.conf'");
// Read the file contents
size_t nread = fread(buff, sizeof(char), sizeof(buff) - 1, file);
if (nread == 0 && !feof(file)) {
perror("Error reading file");
fclose(file);
return 1;
}
buff[nread] = '\0'; // Null-terminate the buffer
printf("Data is %zu\t %.*s\n", nread, (int)nread, buff);
for (int i = 0; i < 10; i++) {
system("lslocks | grep 'bcf.conf'");
sleep(1);
fseek(file , 0 , SEEK_SET);
memset(buff, 0, sizeof(buff));
nread = fread(buff, sizeof(char), sizeof(buff) - 1, file);
if (nread == 0 && !feof(file)) {
perror("Error reading file");
fclose(file);
return 1;
}
buff[nread] = '\0'; // Null-terminate the buffer
printf("Data is %zu\t %.*s\n", nread, (int)nread, buff);
}
fl.l_type = F_UNLCK;
if (fcntl(fileno(file), F_SETLK, &fl) == -1) {
perror("Error unlocking file");
fclose(file);
return 1;
}
printf("File Unlocked Successfully\n");
fclose(file);
return 0;
}
这是我的 CGI:
#!/bin/bash
file=/home/siddusuhaas/sample.conf
exec 200>>"$file"
if ! flock -x 200; then
echo "Unable to acquire lock on file"
exit 1
fi
echo "Surprise! The file is locked!" > "$file"
#Release the lock
exec 200>&-
要获得快速、简单且不那么脏的解决方案,不需要任何特殊工具,请使用
mkdir
。请参阅这篇文章了解一个简单的示例。
mkdir
很简单且原子 - 如果目录不存在,它会创建一个,然后返回成功,所以你知道你,并且只有你拥有锁。如果它不能这样做,它会返回一个错误,所以你知道你现在无法获得锁。
使用一点代码,您可以让它等待,直到它可以轮流,或者检查是否存在超过一定时间的锁并自动删除它,等等。这也可以让您在两者中应用相同的简单逻辑
bash
和 C.
最后一个建议 - 在退出时设置陷阱以删除锁定文件。
您应该尽快明确地删除它,但是意外的程序退出应该尽可能地清理掉它们,锁定文件是一个典型的例子,说明为什么人们不应该在一个简单的
时愉快地使用
kill -9
kill
就可以了。