我用C语言编写了一个程序,该程序会自动在 sqlite3 数据库中创建一个表,并在其中打印第二个值。当我在终端中手动启动该程序时,该程序运行良好。
但是,当我通过在 /etc/rc.local 中执行程序来在启动时运行程序时,它无法正常工作。
重新启动后,程序将启动(我在进程列表中看到它),但是它不会创建任何表,也不会在其中写入值。
我尝试在命令前使用 sudo ,在命令末尾使用&,但它没有任何改变。
我没有这个问题的线索,但是我必须在启动时使该程序正常工作。
那是我的 rc.local 文件。
#!/bin/sh -e
#
# rc.local
#
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
./home/pi/Desktop/RPi_Arduino_Project/rpi5_1 &
exit 0
在启动时尚未启动的是DBMS吗?
是否有可能启动一个终端并在其中执行而不是直接从 rc.local 执行(因为它正在工作)?
编辑:我的程序:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
#include "rs232.h"
#define BUF_SIZE 128 //eventually needs to be bigger
char table_name[256];
int openCOMport(int cport_nr1, int bdrate, char mode[]){
if(RS232_OpenComport(cport_nr1, bdrate, mode)){
printf("Can not open comport 1\n");
return(0);
}
sleep(2);
return(1);
}
int saveinfile(sqlite3 *db, double *output, int rowlength, int newfile){
time_t t = time(0);
struct tm *ts = localtime(&t);
char sql[512];
char *errMsg;
char columnnames[256];
char date_time[256];
int j = 0;
//control terminal output
printf("%02d-%02d-%04d %02d:%02d:%02d ",ts->tm_mday,ts->tm_mon+1,ts->tm_year+1900,ts->tm_hour,ts->tm_min,ts->tm_sec);
for(j=0; j<rowlength; j++){
printf(" %.2f ", output[j]);
}
if(newfile == 1){
sprintf(table_name,"Gas_Sensor_test_%04d_%02d_%02dT%02d_%02d_%02d",ts->tm_year+1900,ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
printf("Table Name: %s\n",table_name);
//Create Table and write header
sprintf(sql, "CREATE TABLE %s (Date date NOT NULL, Time time NOT NULL, HCHO1 float, HCHO2 float, HCHO3 float, FinFlow1 float, FinFlow2 float, PRIMARY KEY(Date, Time));",table_name);
//SQL execution
if(sqlite3_exec(db, sql, NULL, 0, &errMsg) != SQLITE_OK ){
printf("SQL error: %s\n", errMsg);
return(0);
}
}
//insert new rows and print time and date
sprintf(sql,"INSERT INTO %s (Date, Time) VALUES ('%04d-%02d-%02d', '%02d:%02d:%02d');",table_name,ts->tm_year+1900,ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
//printf("SQL Befehl: %s \n",sql); //just control output
if(sqlite3_exec(db, sql, NULL, 0, &errMsg) != SQLITE_OK ){
printf("SQL error: %s\n", errMsg);
return(0);
}
//Write data in table
sprintf(sql,"UPDATE %s SET HCHO1 = %f, HCHO2 = %f, HCHO3 = %f WHERE Date = '%04d-%02d-%02d' AND Time = '%02d:%02d:%02d';",table_name, output[1], output[2],output[3],ts->tm_year+1900,ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
if(sqlite3_exec(db, sql, NULL, 0, &errMsg) != SQLITE_OK ){
printf("SQL error: %s\n", errMsg);
return(0);
}
return (1);
}
int main(){
//port parameters initialization
int cport_nr1=16; // /dev/ttyUSB0
int bdrate=2000000; //Baudrate
char *out; //outputpointer
char delimiter[] = ";"; //Trennzeichen
char mode[]={'8','N','1',0}; //8 data bits, no parity, 1 stop bit
char str_recv[BUF_SIZE]; //recv data buffer
double sensor_value[20]; //array for storing the sensor values
int i;
if(openCOMport(cport_nr1, bdrate, mode) == 0){ //open COMport
return (0);
}
//create database object
sqlite3 *db;
if(sqlite3_open("sensor_tests.db", &db)){
printf("Can't open database");
return(0);
}
int new = 1;
while(1) {
int n = RS232_PollComport(cport_nr1, str_recv, (int)BUF_SIZE);
if(n > 0){
str_recv[n] = '\0'; //always put a "null" at the end of a string!
//printf("Received %i bytes: '%s'\n", n, (char *)str_recv);
}
else if (n == 0){
continue;
}
else{
printf("Error while receiving Data");
return (0);
}
out = strtok(str_recv, delimiter);
i = 0;
while(out != NULL){
//printf("String RECV: %s\n",str_recv);
sensor_value[i]= atof(out); //converting string to double
if(sensor_value[i] < 0){
printf("Sensor value out of range");
}
out = strtok(NULL, delimiter); //next part of input string
printf("Sensor %d: %.2f \n",i+1,sensor_value[i]);
i++;
}
double *psensor_value = sensor_value;
if(saveinfile(db, psensor_value, i, new) == -1){
printf("Error while writing data in file!");
break;
}
new = 0;
}
return(0);
}
答案 0 :(得分:0)
所以我将根据@Yunnosch建议将我的评论转换为答案。
首先,答案是尝试提供有关通常如何调试此类问题的提示。
首先,我建议阅读有关rc.local
和优先级的信息,例如,您可以选择启动哪些守护程序,然后在其中启动脚本,然后可以在脚本中检查该守护程序是否存在。
在您的程序中,始终检查函数的返回值是一个好习惯,因为这样可以使您快速了解出了什么问题。
例如,要检查与数据库的连接是否成功(假设您正在使用sqlite3接口),则可以检查所有错误代码中的sqlite3_open()
returns,其中包含正确的description。从这里可以排除连接是否成功,然后移至下一个功能,依此类推,直到找到根本问题为止。