$ sudo vi /etc/ssh/sshd_config
ClientAliveInterval 120
$ sudo service ssh restart
参考サイト: https://onoredekaiketsu.com/prevent-ssh-connection-timeout/
細かいことだが、これで作業効率が随分変わるような気がする
ソフトウェアエンジニアの技術ブログ:Software engineer tech blog
随机应变 ABCD: Always Be Coding and … : хороший
$ sudo vi /etc/ssh/sshd_config
ClientAliveInterval 120
$ sudo service ssh restart
参考サイト: https://onoredekaiketsu.com/prevent-ssh-connection-timeout/
細かいことだが、これで作業効率が随分変わるような気がする
$ cargo run
error: linking with `cc` failed: exit status: 1
|
= note: LC_ALL=”C” PATH=”/home/ubuntu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/ubuntu/.local/bin:/home/ubuntu/.cargo/bin:/usr/local/sbin:
//
“-nodefaultlibs”
= note: some arguments are omitted. use `–verbose` to show all linker arguments
= note: collect2: fatal error: ld terminated with signal 9 [Killed]
compilation terminated.
最後に、「collect2: fatal error: ld terminated with signal 9 [Killed]」と表示されていますが、これが、メモリ不足のエラーの模様
https://stackoverflow.com/questions/46259776/collect2-fatal-error-ld-terminated-with-signal-9-killed
swapファイルを作成すると、エラーが消えます。
$ sudo fallocate -l 1G /swapfile
$ ls -lh /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ sudo swapon –show
$ free -h
$ pip3 install psycopg2
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
プロジェクトごとに仮想環境を作って、そこでインストールすることが推奨されている。
$ python3 -m venv venv
$ source venv/bin/activate
$ python3 -V
$ pip3 install psycopg2
$ pip3 install python-dotenv
$ cd assets
$ python3 migration.py
$ deactivate
### 仮想環境を作らない方法
$ pip3 install psycopg2 –break-system-packages
これでもいける。
Unix Timeに変換して計算する。UnixTimeは秒単位のため、1日の場合は、60 * 60 * 24 = 86400となる。
let utc_datetime: DateTime<Utc> = DateTime::parse_from_rfc3339("2025-01-01T00:00:00Z").unwrap().into(); println!("{}", utc_datetime.timestamp()); let utc_datetime2: DateTime<Utc> = DateTime::parse_from_rfc3339("2025-01-02T00:00:00Z").unwrap().into(); println!("{}", utc_datetime2.timestamp()); // 86400 println!("{}", utc_datetime2.timestamp() - utc_datetime.timestamp());
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.24s
Running `target/debug/app`
1735689600
1735776000
86400
経過時間は、unixtimeの差を86400で割れば日数となるので、
let base_date = "2025-01-01T00:00:00Z".to_string(); let utc_datetime: DateTime<Utc> = DateTime::parse_from_rfc3339(&base_date).unwrap().into(); let utc_datetime2: DateTime<Utc> = Utc::now(); println!("{}", utc_datetime2.timestamp()); println!("{}", (utc_datetime2.timestamp() - utc_datetime.timestamp()) / 86400);
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.67s
Running `target/debug/app`
1741587141
68
1月1日から、68日経過していることになる。
psycopg2 の execute は、commitの前に連続して実行できる。そのため、以下のように、sql文をforループで回すことができる。
import psycopg2 import os from dotenv import load_dotenv load_dotenv('../.env') PSQL_PASSWORD = os.getenv('PSQL_PASSWORD') connection = psycopg2.connect( host='localhost', user='postgres', password=PSQL_PASSWORD ) cur = connection.cursor() sql1 = "CREATE TABLE IF NOT EXISTS person1 ( \ id SERIAL PRIMARY KEY, \ name TEXT NOT NULL, \ data BYTEA \ );" sql2 = "CREATE TABLE IF NOT EXISTS person2 ( \ id SERIAL PRIMARY KEY, \ name TEXT NOT NULL, \ data BYTEA \ );" sqls = [sql1, sql2] for sql in sqls: cur.execute(sql) connection.commit() cur.close() connection.close()
$ python3 migration.py
# \dt
List of relations
Schema | Name | Type | Owner
——–+———-+——-+———-
public | person1 | table | postgres
public | person2 | table | postgres
なるほどー
$ pip install python-dotenv
.env
PSQL_PASSWORD=hoge
import os from dotenv import load_dotenv load_dotenv('../.env') PSQL_PASSWORD = os.getenv('PSQL_PASSWORD') print(PSQL_PASSWORD)
$ python3 migration.py
hoge
$ tree
.
├── config
│ ├── hoge.dat
│ └── secret.pem
├── index.html
├── log
│ └── log.txt
├── src
│ └── main.rs
└── target
.gitignore
target/ congif/ target/ log/*.txt .env
git push
これだと、logやconfigの空フォルダが生成できない。
.gitkeepをフォルダの中に置いて、以下のように書く
!config/ config/* !config/.gitkeep !log/ log/*.txt !log/.gitkeep target/ .env
すると、logやconfigは空フォルダができるが、中のファイル群は更新されない。
OK!
async fn handle_index()-> Response { let mut name_list: Vec<Name> = Vec::new(); let name1 = Name { family: "tanaka".to_string(), first: "taro".to_string(), age: 12}; let name2 = Name { family: "yamada".to_string(), first: "koji".to_string(), age: 13}; let name3 = Name { family: "okamoto".to_string(), first: "ai".to_string(), age: 14}; name_list.push(name1); name_list.push(name2); name_list.push(name3); let name_list_serialized = serde_json::json!(&name_list); let mut post_url = format!("http://192.168.33.10:3000/fetch"); let client = reqwest::Client::new(); let resp = client.post(post_url) .header(reqwest::header::CONTENT_TYPE, "application/json") .json(&name_list_serialized) .send() .await .unwrap(); // println!("{:?}", resp); "All good".into_response() } async fn handle_fetch(extract::Json(names): extract::Json<Vec<Name>>)-> Response { println!("get names: {:?}", names); let file_path = format!("./data/names.txt"); if !Path::new(&file_path.clone()).exists() { let mut file = File::create(file_path.clone()).unwrap(); for name in names { let serialized: Vec<u8> = serde_json::to_vec(&name).unwrap(); file.write_all(&serialized).expect("write failed"); file.write_all(b"\n").expect("write failed"); } println!("done"); } else { println!("file exist"); } "All good".into_response() }
names.txt
{“family”:”tanaka”,”first”:”taro”,”age”:12}
{“family”:”yamada”,”first”:”koji”,”age”:13}
{“family”:”okamoto”,”first”:”ai”,”age”:14}
うん、期待通りです。
[i32; 10]からStringへの変換
let mut bf = BloomFilter { filter: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}; bf.set_v("hello world".to_string()); println!("{:?}", bf.filter); let mut bloom_str = String::new(); for i in bf.filter { bloom_str = format!("{}{}", bloom_str, i); } println!("{}", bloom_str);
String(chars)から[i32; n]への変換
let str = "2201211222".to_string(); let mut filter:[i32;10] = [0,0,0,0,0,0,0,0,0,0]; for (i,c) in str.chars().enumerate() { filter[i] = (c.to_string()).parse::<i32>().unwrap(); } println!("{:?}", filter);
[2, 2, 0, 1, 2, 1, 1, 2, 2, 2]
websocketで、send_textはあるけど、send_binary, sendしかなく、配列の送り方が不明なので、[i32; n]を文字列に変換して、受け取った側で、[i32; n]に戻すという処理にしている。
うーん、 なんか
websocketで通信して、connection errorや、通信内容の処理でのエラーハンドリング
以下のように書くと、接続先のURLにミスがあった場合もerrorを返してくれる。
#[tokio::main] async fn main() { let url = format!("wss://echo.websocket.org/"); // let url = format!("wss://echo.aaaaaaa.org/"); let res = web_socket(url).await; match res { Ok(_) => { println!("wsに成功しました!"); } Err(error) => { println!("wsに失敗"); println!("{}", error); } } } async fn web_socket(url: String) -> Result<(), Box<dyn std::error::Error>> { let mut ws = WebSocket::connect(&url).await?; ws.send_text("foo".to_string()).await?; ws.receive().await?; if let Frame::Text { payload: received_msg, .. } = ws.receive().await? { println!("{}", received_msg); if received_msg != "hoge" { let error = "メッセージの照合に失敗しました。".to_string(); return Err(error.into()); } } ws.close(None).await?; Ok(()) }
– connectionエラー
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.17s
Running `target/debug/app`
wsに失敗
could not parse into SocketAddrs
– ソケット通信での内容でのエラーを明示的にエラーとして知らせる
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.81s
Running `target/debug/app`
foo
wsに失敗
メッセージの照合に失敗しました。
– 成功時
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.58s
Running `target/debug/app`
foo
wsに成功しました!
以下のような書き方はできない。
let mut ws = WebSocket::connect(&url).await?; match ws { Ok(_) => { println!("wsに成功しました!"); } Err(error) => { println!("wsに失敗"); println!("{}", error); } }
なるほど、これは面白い。