[Web CV] Deploy MobileNet for the web
<实践复现此项目>
课程:https://www.coursera.org/learn/browser-based-models-tensorflow/home/welcome
代码:https://github.com/lmoroney/dlaicourse
参考:[MobileNet] Train MobilenNet in Keras & TF Hub
Jeff 2020: 直接跳到"项目复现"即可。
基础练习
一、the first training.
Build a model, but not load a model, and then training.
<html> <head></head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script> <script lang="js"> async function doTraining(model){ const history = await model.fit(xs, ys, { epochs: 500, callbacks:{ onEpochEnd: async(epoch, logs) =>{ console.log("Epoch:" + epoch + " Loss:" + logs.loss); } } }); } const model = tf.sequential(); model.add(tf.layers.dense({units: 1, inputShape: [1]})); model.compile({loss:'meanSquaredError', optimizer:'sgd'}); model.summary(); const xs = tf.tensor2d([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], [6, 1]); const ys = tf.tensor2d([-3.0, -1.0, 2.0, 3.0, 5.0, 7.0], [6, 1]); doTraining(model).then(() => { alert(model.predict(tf.tensor2d([10], [1,1]))); }); </script> <body> <h1>First HTML Page</h1> </body> </html>
二、训练可视化
三、Image Classification Using MobileNet
When you launch the mobilenet.html file in the Chrome browser make sure to open the Developer Tools to see the output in the Console.
<html> <head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"> </script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet@1.0.0"> </script> </head> <body> <img id="img" src="coffee.jpg"></img> <div id="output" style="font-family:courier;font-size:24px;height=300px"></div> </body> <script> const img = document.getElementById('img'); const outp = document.getElementById('output'); mobilenet.load().then(model => { model.classify(img).then(predictions => { console.log(predictions); for(var i = 0; i<predictions.length; i++){ outp.innerHTML += "<br/>" + predictions[i].className + " : " + predictions[i].probability; } }); }); </script> </html>
自定义模型
线性模型
一、简单的线性模型
模型定义
model = tf.keras.models.Sequential([ # Note the input shape is the desired size of the image 150x150 with 3 bytes color tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(32, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2),
# --------------------------------------------------- # Flatten the results to feed into a DNN tf.keras.layers.Flatten(), # 512 neuron hidden layer tf.keras.layers.Dense(512, activation='relu'), # Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('cats') and 1 for the other ('dogs') tf.keras.layers.Dense(1, activation='sigmoid') ])
确实没有MobileNet的收敛速度快.

Train for 100 steps, validate for 50 steps Epoch 1/15 100/100 - 19s - loss: 0.7329 - accuracy: 0.5675 - val_loss: 0.6213 - val_accuracy: 0.6590 Epoch 2/15 100/100 - 18s - loss: 0.6094 - accuracy: 0.6920 - val_loss: 0.5722 - val_accuracy: 0.7210 Epoch 3/15 100/100 - 18s - loss: 0.5236 - accuracy: 0.7470 - val_loss: 0.5856 - val_accuracy: 0.7050 Epoch 4/15 100/100 - 19s - loss: 0.4484 - accuracy: 0.7925 - val_loss: 0.7536 - val_accuracy: 0.6630 Epoch 5/15 100/100 - 20s - loss: 0.3529 - accuracy: 0.8350 - val_loss: 0.5920 - val_accuracy: 0.7170 Epoch 6/15 100/100 - 19s - loss: 0.2833 - accuracy: 0.8795 - val_loss: 0.6584 - val_accuracy: 0.7250 Epoch 7/15 100/100 - 19s - loss: 0.2161 - accuracy: 0.9155 - val_loss: 0.8035 - val_accuracy: 0.7250 Epoch 8/15 100/100 - 19s - loss: 0.1417 - accuracy: 0.9420 - val_loss: 0.9094 - val_accuracy: 0.7110 Epoch 9/15 100/100 - 19s - loss: 0.1083 - accuracy: 0.9575 - val_loss: 1.0949 - val_accuracy: 0.7290 Epoch 10/15 100/100 - 20s - loss: 0.0729 - accuracy: 0.9735 - val_loss: 1.2127 - val_accuracy: 0.7310 Epoch 11/15 100/100 - 20s - loss: 0.0610 - accuracy: 0.9785 - val_loss: 1.4155 - val_accuracy: 0.7110 Epoch 12/15 100/100 - 20s - loss: 0.0601 - accuracy: 0.9825 - val_loss: 1.0516 - val_accuracy: 0.6820 Epoch 13/15 100/100 - 20s - loss: 0.0527 - accuracy: 0.9860 - val_loss: 2.0745 - val_accuracy: 0.7280 Epoch 14/15 100/100 - 19s - loss: 0.0826 - accuracy: 0.9825 - val_loss: 1.7811 - val_accuracy: 0.7290 Epoch 15/15 100/100 - 19s - loss: 0.0669 - accuracy: 0.9855 - val_loss: 1.8485 - val_accuracy: 0.7060
二、模型保存
浏览器端直接下载文件.
const saveResult = model.save('downloads://model');
MobileNet模型
一、加载预训练模型
let mobilenet; let model; const webcam = new Webcam(document.getElementById('wc')); const dataset = new RPSDataset();
var rockSamples=0, paperSamples=0, scissorsSamples=0; let isPredicting = false;
//--------------------------------------------------------
async function loadMobilenet() { const mobilenet = await tf.loadLayersModel('https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json'); const layer = mobilenet.getLayer('conv_pw_13_relu'); return tf.model({inputs: mobilenet.inputs, outputs: layer.output}); } async function init(){ await webcam.setup(); mobilenet = await loadMobilenet(); tf.tidy(() => mobilenet.predict(webcam.capture())); } init();
二、准备数据
label = parseInt(elem.id); const img = webcam.capture();
dataset.addExample(mobilenet.predict(img), label);
训练数据的保存:
class RPSDataset {
constructor() { this.labels = [] } addExample(example, label) { if (this.xs == null) { this.xs = tf.keep(example); // The tensor to keep from being disposed. this.labels.push(label); } else { const oldX = this.xs; this.xs = tf.keep(oldX.concat(example, 0)); this.labels.push(label); oldX.dispose(); } }
// for training process. encodeLabels(numClasses) { for (var i = 0; i < this.labels.length; i++) { if (this.ys == null) { this.ys = tf.keep(tf.tidy( () => {return tf.oneHot( tf.tensor1d([this.labels[i]]).toInt(), numClasses)})); } else { const y = tf.tidy( () => {return tf.oneHot( tf.tensor1d([this.labels[i]]).toInt(), numClasses)}); const oldY = this.ys; this.ys = tf.keep(oldY.concat(y, 0)); oldY.dispose(); y.dispose(); } } } }
三、训练数据
async function train() {
dataset.ys = null; dataset.encodeLabels(3); // 给ys赋值完毕
model = tf.sequential({ layers: [ tf.layers.flatten({inputShape: mobilenet.outputs[0].shape.slice(1)}), tf.layers.dense({ units: 100, activation: 'relu'}), tf.layers.dense({ units: 3, activation: 'softmax'}) ] });
const optimizer = tf.train.adam(0.0001); model.compile({optimizer: optimizer, loss: 'categoricalCrossentropy'});
let loss = 0; model.fit(dataset.xs, dataset.ys, { epochs: 10, callbacks: { onBatchEnd: async (batch, logs) => { loss = logs.loss.toFixed(5); console.log('LOSS: ' + loss); } } }); }
项目复现
一、代码下载
项目代码: Retrain MobileNet for the web
二、迁移学习
选择合适的版本:
AttributeError: module 'tensorflow' has no attribute 'app' #34431
Issue: cannot import name 'image_module_info_pb2'
Goto: Creating the TensorFlow Hub pip package using Linux
开始训练:
# cd /path/to/retrain-mobilenet-v1
python -m scripts.retrain -h
# Create folders
mkdir -p tf_files/{bottlenecks,dataset,models,training_summaries}
# Add your dataset
cp -R /path/to/my-dataset/* tf_files/dataset
# Set environment variables
IMAGE_SIZE=128
ARCHITECTURE=mobilenet_0.25_$IMAGE_SIZE
# Start training
python -m scripts.retrain \
--image_dir=tf_files/dataset \
--model_dir=tf_files/models \
--architecture=$ARCHITECTURE \
--output_graph=tf_files/retrained_graph.pb \
--output_labels=tf_files/retrained_labels.txt \
--bottleneck_dir=tf_files/bottlenecks \
--summaries_dir=tf_files/training_summaries/$ARCHITECTURE \
--how_many_training_steps=400 \
--learning_rate=0.001
训练结果:
$ls tf_files/
frozen_graph.pb labels.txt quantized_graph.pb
三、测试模型
测试成功,完美。
$ python scripts/label_image.py --graph=tf_files/retrained_graph.pb --input_width=$IMAGE_SIZE --input_height=$IMAGE_SIZE --image=tf_files/dataset/positive_isDemage/3_roiImg1.jpg
WARNING:tensorflow:From scripts/label_image.py:29: The name tf.GraphDef is deprecated. Please use tf.compat.v1.GraphDef instead. WARNING:tensorflow:From scripts/label_image.py:42: The name tf.read_file is deprecated. Please use tf.io.read_file instead. WARNING:tensorflow:From scripts/label_image.py:56: The name tf.image.resize_bilinear is deprecated. Please use tf.compat.v1.image.resize_bilinear instead. WARNING:tensorflow:From scripts/label_image.py:58: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead. 2020-06-10 13:28:10.983890: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA 2020-06-10 13:28:11.004028: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 1999965000 Hz 2020-06-10 13:28:11.004412: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x557d967b5fe0 initialized for platform Host (this does not guarantee that XLA will be used). Devices: 2020-06-10 13:28:11.004438: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version WARNING:tensorflow:From scripts/label_image.py:65: The name tf.gfile.GFile is deprecated. Please use tf.io.gfile.GFile instead. Evaluation time (1-image): 0.068s positive isdemage (score=0.50109) negative isdemage (score=0.49891)
四、Optimize for the web
模型压缩
大小没什么变化;压缩后就能看到quantized的效果。
$ python ./scripts/quantize_graph.py --input=tf_files/retrained_graph.pb --output=tf_files/quantized_graph.pb --output_node_names=final_result --mode=weights_rounded
WARNING:tensorflow:From ./scripts/quantize_graph.py:1191: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.compat.v1.graph_util.extract_sub_graph` W0610 15:01:24.278689 139993801140032 deprecation.py:323] From ./scripts/quantize_graph.py:1191: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.compat.v1.graph_util.extract_sub_graph` WARNING:tensorflow:From ./scripts/quantize_graph.py:1294: FastGFile.__init__ (from tensorflow.python.platform.gfile) is deprecated and will be removed in a future version. Instructions for updating: Use tf.gfile.GFile. W0610 15:01:24.287163 139993801140032 deprecation.py:323] From ./scripts/quantize_graph.py:1294: FastGFile.__init__ (from tensorflow.python.platform.gfile) is deprecated and will be removed in a future version. Instructions for updating: Use tf.gfile.GFile.
jeffrey@unsw-ThinkPad-T490:retrain-mobilenet-v1$ ls tf_files/ -l total 3948 drwxr-xr-x 4 jeffrey jeffrey 4096 Jun 10 13:15 bottlenecks drwxr-xr-x 4 jeffrey jeffrey 4096 Jun 10 13:09 dataset drwxr-xr-x 3 jeffrey jeffrey 4096 Jun 10 13:15 models -rw-r--r-- 1 jeffrey jeffrey 2008026 Jun 10 15:01 quantized_graph.pb -rw-r--r-- 1 jeffrey jeffrey 2008024 Jun 10 13:15 retrained_graph.pb -rw-r--r-- 1 jeffrey jeffrey 36 Jun 10 13:15 retrained_labels.txt drwxr-xr-x 3 jeffrey jeffrey 4096 Jun 10 13:15 training_summaries
$ gzip -k tf_files/retrained_graph.pb tf_files/quantized_graph.pb $ du -h tf_files/*.gz 640K tf_files/quantized_graph.pb.gz 1.8M tf_files/retrained_graph.pb.gz
Convert to TensorFlow.js model
转化为 tfjs模型。
$ tensorflowjs_converter \ --input_format=tf_frozen_model \ --output_node_names=final_result \ tf_files/quantized_graph.pb \ tf_files/web

2020-06-10 15:19:58.882846: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:786] Optimization results for grappler item: graph_to_optimize 2020-06-10 15:19:58.882905: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] debug_stripper: debug_stripper did nothing. time = 0.128ms. 2020-06-10 15:19:58.882913: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] model_pruner: Graph size after: 420 nodes (-140), 446 edges (-140), time = 4.258ms. 2020-06-10 15:19:58.882918: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 176 nodes (-244), 175 edges (-271), time = 21.271ms. 2020-06-10 15:19:58.882924: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 176 nodes (0), 175 edges (0), time = 4.154ms. 2020-06-10 15:19:58.882929: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 174 nodes (-2), 173 edges (-2), time = 1.247ms. 2020-06-10 15:19:58.882935: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] model_pruner: Graph size after: 174 nodes (0), 173 edges (0), time = 0.873ms. 2020-06-10 15:19:58.882941: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 174 nodes (0), 173 edges (0), time = 3.476ms. 2020-06-10 15:19:58.882947: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 3.773ms. 2020-06-10 15:19:58.882953: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 1.043ms. 2020-06-10 15:19:58.882960: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] debug_stripper: debug_stripper did nothing. time = 0.261ms. 2020-06-10 15:19:58.882968: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] model_pruner: Graph size after: 174 nodes (0), 173 edges (0), time = 0.81ms. 2020-06-10 15:19:58.882975: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 174 nodes (0), 173 edges (0), time = 3.222ms. 2020-06-10 15:19:58.882983: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 3.627ms. 2020-06-10 15:19:58.882990: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 1.035ms. 2020-06-10 15:19:58.882997: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] model_pruner: Graph size after: 174 nodes (0), 173 edges (0), time = 0.742ms. 2020-06-10 15:19:58.883004: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 174 nodes (0), 173 edges (0), time = 3.115ms. 2020-06-10 15:19:58.883012: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 3.579ms. 2020-06-10 15:19:58.883019: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 174 nodes (0), 173 edges (0), time = 1.055ms. 2020-06-10 15:19:58.923034: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:786] Optimization results for grappler item: graph_to_optimize 2020-06-10 15:19:58.923056: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] remapper: Graph size after: 173 nodes (-1), 172 edges (-1), time = 0.691ms. 2020-06-10 15:19:58.923080: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 173 nodes (0), 172 edges (0), time = 3.373ms. 2020-06-10 15:19:58.923088: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 173 nodes (0), 172 edges (0), time = 3.672ms. 2020-06-10 15:19:58.923095: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 173 nodes (0), 172 edges (0), time = 0.965ms. 2020-06-10 15:19:58.923102: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] remapper: Graph size after: 173 nodes (0), 172 edges (0), time = 0.734ms. 2020-06-10 15:19:58.923108: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] constant_folding: Graph size after: 173 nodes (0), 172 edges (0), time = 2.933ms. 2020-06-10 15:19:58.923115: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] arithmetic_optimizer: Graph size after: 173 nodes (0), 172 edges (0), time = 3.192ms. 2020-06-10 15:19:58.923122: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:788] dependency_optimizer: Graph size after: 173 nodes (0), 172 edges (0), time = 1.091ms. Writing weight file tf_files/web/model.json...
模型压缩
1.9M压缩为953kb,压缩率大约50%。
$ gzip -k tf_files/web/ group1-shard1of1.bin model.json
jeffrey@unsw-ThinkPad-T490:retrain-mobilenet-v1$ gzip -k tf_files/web/group1-shard1of1.bin jeffrey@unsw-ThinkPad-T490:retrain-mobilenet-v1$ ll tf_files/web/ total 2836 drwxr-xr-x 2 jeffrey jeffrey 4096 Jun 10 15:24 ./ drwxr-xr-x 7 jeffrey jeffrey 4096 Jun 10 15:19 ../ -rw-r--r-- 1 jeffrey jeffrey 1883348 Jun 10 15:19 group1-shard1of1.bin -rw-r--r-- 1 jeffrey jeffrey 953972 Jun 10 15:19 group1-shard1of1.bin.gz -rw-r--r-- 1 jeffrey jeffrey 56654 Jun 10 15:19 model.json
继续压缩:70.3kB

jeffrey@unsw-ThinkPad-T490:differ2_pb$ xxd quantized_graph.pb > file1.hex jeffrey@unsw-ThinkPad-T490:differ2_pb$ xxd quantized_graph_old.pb > file2.hex jeffrey@unsw-ThinkPad-T490:differ2_pb$ diff file1.hex file2.hex > log.diff jeffrey@unsw-ThinkPad-T490:differ2_pb$ ll total 30988 drwxr-xr-x 2 jeffrey jeffrey 4096 Jun 10 15:49 ./ drwxr-xr-x 10 jeffrey jeffrey 4096 Jun 10 15:43 ../ -rw-r--r-- 1 jeffrey jeffrey 8534130 Jun 10 15:49 file1.hex -rw-r--r-- 1 jeffrey jeffrey 8534130 Jun 10 15:49 file2.hex -rw-r--r-- 1 jeffrey jeffrey 10628750 Jun 10 15:49 log.diff -rw-r--r-- 1 jeffrey jeffrey 2008026 Jun 10 15:44 quantized_graph_old.pb -rw-r--r-- 1 jeffrey jeffrey 2008026 Jun 10 15:41 quantized_graph.pb

jeffrey@unsw-ThinkPad-T490:differ1_bin$ ll total 19400 drwxr-xr-x 2 jeffrey jeffrey 4096 Jun 10 15:48 ./ drwxr-xr-x 10 jeffrey jeffrey 4096 Jun 10 15:43 ../ -rw-r--r-- 1 jeffrey jeffrey 8004268 Jun 10 15:47 file1.hex -rw-r--r-- 1 jeffrey jeffrey 8004268 Jun 10 15:48 file2.hex -rw-r--r-- 1 jeffrey jeffrey 1883348 Jun 10 15:42 group1-shard1of1.bin -rw-r--r-- 1 jeffrey jeffrey 1883348 Jun 10 15:19 group1-shard1of1_old.bin -rw-r--r-- 1 jeffrey jeffrey 70316 Jun 10 15:48 log.diff
Add labels
# Install 'jq' once with homebrew (https://brew.sh/) brew install jq # Create JSON file from newline-delimited text file cat tf_files/retrained_labels.txt | jq -Rsc '. / "\n" - [""]' > tf_files/web/labels.json cat tf_files/web/labels.json
五、Deploy on the web
tensorflowjs_model.pb, weights_manifest.json如何来的?
此项目链接web page demo有问题,需看最新的readme,如下:
https://github.com/tensorflow/tfjs-examples/tree/master/mobilenet [可用]
https://github.com/tensorflow/tfjs/tree/master/tfjs-converter/demo/mobilenet [命令参考]
$ npm install
$ npm run build > tfjs-examples-mobilenet@0.1.0 build /home/jeffrey/Desktop/tfjs-examples-master/mobilenet > cross-env NODE_ENV=production parcel build index.html --no-minify --public-url ./ ✨ Built in 1.75s. dist/mobilenet.1fda360a.map ⚠️ 5.1 MB 472ms dist/mobilenet.ea2308db.js ⚠️ 1.34 MB 1.07s dist/tfjs-examples.c3b5157d.css 280.77 KB 7ms dist/cat.d8f4b943.jpg 40.08 KB 8ms dist/index.html 2.5 KB 3ms
jeff@unsw-ThinkPad-T490:mobilenet$ ls cat.jpg dist imagenet_classes.js index.html index.js node_modules package.json README.md yarn.lock
我们就可以像打开静态网页一样打开我们完成的项目。
打包生成的dist文件夹,其中index.html为入口文件。
六、布置静态网页
Ref: Ubuntu 18.04系统中使用Apache搭建简单的web服务器
安装命令:
sudo apt install apache2 -y
启动 Web 服务器:
jeffrey@unsw-ThinkPad-T490:~$ systemctl status apache2 systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: Drop-In: /lib/systemd/system/apache2.service.d └─apache2-systemd.conf Active: active (running) since Thu 2020-06-11 09:54:41 AEST; 10s ago Main PID: 31523 (apache2) Tasks: 55 (limit: 4915) CGroup: /system.slice/apache2.service ├─31523 /usr/sbin/apache2 -k start ├─31524 /usr/sbin/apache2 -k start └─31525 /usr/sbin/apache2 -k start jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ /etc/init.d/apache2 start [....] Starting apache2 (via systemctl): apache2.service/bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) . ok jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ /etc/init.d/apache2 stop [....] Stopping apache2 (via systemctl): apache2.service/bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) . ok jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ jeffrey@unsw-ThinkPad-T490:~$ /etc/init.d/apache2 restart [....] Restarting apache2 (via systemctl): apache2.service/bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemctl: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libcryptsetup.so.12) /bin/systemd-tty-ask-password-agent: /usr/local/anaconda3/lib/libuuid.so.1: no version information available (required by /lib/x86_64-linux-gnu/libblkid.so.1) . ok
遇到CORS问题:
$ google-chrome --disable-web-security
修改 Nginx 后台配置文件
Nginx命令参考:如何在Ubuntu 18.04上安装Nginx
现在您的Web服务器已启动并运行,让我们来回顾一些基本的管理命令。
要停止您的Web服务器,请键入: sudo systemctl stop nginx 停止时要启动Web服务器,请输入: sudo systemctl start nginx 要停止并再次启动服务,请键入: sudo systemctl restart nginx 如果您只是简单地进行配置更改,Nginx通常可以重新加载而不会丢失连接。 为此,请输入: sudo systemctl reload nginx 默认情况下,Nginx配置为在服务器引导时自动启动。 如果这不是您想要的,可以通过输入以下命令来禁用此行为: sudo systemctl disable nginx 要重新启用服务以在启动时启动,您可以键入: sudo systemctl enable nginx
Nginx配置实例
实例一:允许example.com的应用在www.example2.com上跨域提取数据
在nginx.conf里找到server项,并在里面添加如下配置
1
|
location /{
|
如果需要允许来自任何域的访问,可以这样配置
1
|
add_header Access-Control-Allow-Origin *;
|
End.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律