mirror of
https://github.com/midoks/mdserver-web
synced 2026-11-06 00:55:59 +08:00
Compare commits
1018 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f2eb3fc3b | |||
| c4047b5ef1 | |||
| 65d039bf48 | |||
| 70092129e4 | |||
| 556471908d | |||
| 109405b54b | |||
| 9795ae23c7 | |||
| 1979a02cd5 | |||
| 39b14b92de | |||
| b8a5c4d178 | |||
| 7a20f56335 | |||
| e18bd098d9 | |||
| 8aaa3cfab6 | |||
| 02a9f84c13 | |||
| 23320865b0 | |||
| 6f365e122a | |||
| e3229efe1b | |||
| 710acecff7 | |||
| 9c7a155be0 | |||
| 157a5da6f1 | |||
| 7ee5ed5808 | |||
| e8a96959a5 | |||
| a4845acbb6 | |||
| fec638007c | |||
| 80f7a0de38 | |||
| a3bb9ac80a | |||
| 3dcc6e3349 | |||
| 60870a4e5d | |||
| ea635bc960 | |||
| 749c8443ee | |||
| 052120c25e | |||
| a2b3b86c43 | |||
| 6d57e3dd40 | |||
| a67689d890 | |||
| b6bffedf06 | |||
| e07eaf4226 | |||
| dd9e9d4899 | |||
| cd1d80915a | |||
| 40f64ab3e8 | |||
| 69ba921ec4 | |||
| 255fbcd688 | |||
| 24e12b70c8 | |||
| 0feee48ea8 | |||
| 5cd8c5ae2c | |||
| 28a75eaedc | |||
| 50d0794f4a | |||
| 755e53f4d7 | |||
| 1876027bd2 | |||
| 26b06f9bb2 | |||
| 8f67d35260 | |||
| 7fa78c78e2 | |||
| ae7276300f | |||
| 420816ff4e | |||
| df34a7ef9b | |||
| e1b199c8d5 | |||
|
|
e6060847ef | ||
| 7ff1530684 | |||
| cd0ad7488e | |||
| 6a0f81154a | |||
|
|
096c736c28 | ||
| 7d01a487dc | |||
| ba95ef1537 | |||
| 01035018c4 | |||
| 8aa12b979a | |||
| 98dc9e5bd8 | |||
| 4ebadc28c9 | |||
| 02115226fa | |||
| f661aea83c | |||
| cfd3abf97b | |||
| b5d1c8cfcf | |||
| 98156cc1cb | |||
| 33a0dc6014 | |||
| 95a6f86e5d | |||
| 74ac55b01d | |||
| 518cc78670 | |||
| 43727decf0 | |||
| 599b3a7f4a | |||
| bf6c18c57a | |||
| 34838bb238 | |||
| 1a356e516c | |||
| 15e273aa6f | |||
|
|
4c3d3bf41d | ||
| f782bacc64 | |||
| 7e62ab62f9 | |||
| aaa8644348 | |||
| 53797c7f56 | |||
| c9302f406e | |||
| 7ad881c8ad | |||
| 015e57f96d | |||
| 84b94a172e | |||
| c1380945ef | |||
| 2d80df003e | |||
| 568cdaa0ad | |||
| d11e4807df | |||
|
|
f6bc08cec1 | ||
| d723afb96e | |||
|
|
6c2aa089f3 | ||
| 35e1ff2e96 | |||
| bee9e89ed5 | |||
| d0b622906f | |||
| 56f7edcb55 | |||
| 4acbc0363f | |||
| 79013db685 | |||
|
|
eb5b5e5ce8 | ||
| b9e6469635 | |||
| 56ab927f8c | |||
| 3d74320e76 | |||
| 0371eaa37a | |||
| 713dbfcda5 | |||
| 93ef2848ed | |||
| 8750cf0f74 | |||
| af32a1e54d | |||
| 2a7c63029a | |||
| f8fe7bea19 | |||
| ef2814bafe | |||
| 220fef5f4d | |||
| 2835c111d0 | |||
| 6d0dcf3112 | |||
| 28307ce8e8 | |||
| 282fbed37d | |||
| 101b6d06bc | |||
| 8de4c74696 | |||
| ba62972820 | |||
| ec512f50af | |||
| 3261f54649 | |||
| ec38ba9e21 | |||
| 9e1dc94a08 | |||
| 40a76ac81e | |||
| 721245b9ad | |||
| cb4ae9b74f | |||
|
|
5524ecf4e0 | ||
| dbb2718892 | |||
| 88fc903d80 | |||
|
|
242c30f7cb | ||
| c944b7c585 | |||
| dc2e2695be | |||
| f5b86ea189 | |||
| b6c2f7f3a1 | |||
| 81003f75b7 | |||
| d6dc330083 | |||
| fd0cbe10fc | |||
| 4ed77e82be | |||
|
|
de0e89f056 | ||
| 29da5146f6 | |||
| e951089b45 | |||
| 909d65ad83 | |||
| 27cac55b8f | |||
| 0ee6ae3713 | |||
| fb97160cfb | |||
| 96b00526fe | |||
| 909fe6d0f1 | |||
| f2e9f4c5e8 | |||
| 3b629b1296 | |||
| 5cee415030 | |||
|
|
141e52d42a | ||
| 1b21f3c814 | |||
| 4ddc2fef8e | |||
| 18b259a5a5 | |||
| 2e2288a691 | |||
| d03ae1db7b | |||
| 418355a571 | |||
| 340b53aa62 | |||
| dd0628a7fb | |||
| 3e5b48d2ad | |||
|
|
815148a722 | ||
| 47aadfd877 | |||
| 42bfd9a934 | |||
| 55df1b7613 | |||
| 6bc3fc5707 | |||
| 19771181dd | |||
| f0b65332bd | |||
| 7dd8a1eb4f | |||
| f584c18d7e | |||
| b023044473 | |||
| dfa7ffdb53 | |||
| a5a6eb7e5f | |||
| eac88f1d26 | |||
| 518f693948 | |||
| 43684e9b20 | |||
| 59a7bb5584 | |||
| f623fd9dcf | |||
| 9db36d45af | |||
| ff5670797a | |||
| 54ad7e5fd0 | |||
| 2970aa4b8c | |||
| d2e5751542 | |||
| ba5f6f4958 | |||
| b220552f92 | |||
| d02981cee5 | |||
| 96d5246415 | |||
| ea284049c0 | |||
| 5c44bb10d1 | |||
| c7c834fb75 | |||
| 2ade5e490c | |||
| 6c61d3f3c0 | |||
| ab19878a80 | |||
| c27abfde3c | |||
| 411b21cdec | |||
| 26e21e631d | |||
|
|
653068f2c2 | ||
| 188c63826f | |||
| 1820fc724f | |||
| 645519b983 | |||
| f97e015bbc | |||
| 9d47a385f5 | |||
| ca06c68d24 | |||
| 841873418c | |||
| 05a6f093ab | |||
| a916104d33 | |||
| 4609c360ac | |||
| b3acf3647f | |||
| 400c9d1276 | |||
|
|
59bd655bb1 | ||
| 8227253b74 | |||
| 4e5604dc27 | |||
| 2e238e6982 | |||
| c5df0f256c | |||
| 6bd73131ce | |||
| 309422a41c | |||
| 6aa7d9dc20 | |||
| 565e1cc882 | |||
|
|
5c1e292da9 | ||
| 6db1ee133d | |||
|
|
383cec2ee5 | ||
| dfa2163407 | |||
| ed9a9b7860 | |||
| 5af49dc081 | |||
| d4f425abf8 | |||
| 1867ee01f1 | |||
| 81fe83e0a1 | |||
| f266ec86c0 | |||
| e5d6357fae | |||
| 7967b36088 | |||
| d7471fe882 | |||
| b4b67c8f48 | |||
| 63ae895f12 | |||
| 5dd77ee747 | |||
| 6071dfa5f1 | |||
| 11d8d813d2 | |||
| f337a60dc1 | |||
| 33f66ab3b1 | |||
| eb71732d20 | |||
| fbc9340960 | |||
| a2f14f4121 | |||
| ce8c7474ce | |||
| 85d9f1409a | |||
| c29dfee004 | |||
| 618f938462 | |||
| 4e7927f9bc | |||
| 212f29438d | |||
| 3b6d9c3310 | |||
| c01cb01d71 | |||
| 712863b766 | |||
| 601a80950f | |||
| 9f46ceac33 | |||
| ad9b9be7fe | |||
| 2be6ac36ef | |||
| fdb8ca205f | |||
| f1024c165a | |||
| 9efc85f10d | |||
| dd592b40ee | |||
| 9103646150 | |||
| cae2680862 | |||
| e3099a946b | |||
| 3f1da50025 | |||
| fbd70eb4f9 | |||
| ef0d6d5265 | |||
| 1e6932cd01 | |||
| d173586d49 | |||
| 717269dadc | |||
| 21c4f93e02 | |||
| c36a03bfb3 | |||
| a71927917c | |||
| 2f5d5835c5 | |||
| e95b42df77 | |||
| 5c6dbbbb0c | |||
| a151516eab | |||
| 3a590c7feb | |||
| e9f0e1962e | |||
| c4fda1362d | |||
| f31343b2a5 | |||
| 90b414d373 | |||
| 3eab70db4c | |||
| e0810bb8d6 | |||
| 96a32d5c8f | |||
| d45cfb5fe8 | |||
| 08753ae96d | |||
| 465e55848f | |||
| 4492a97155 | |||
| ba46d568bf | |||
| d87d5d5349 | |||
| 76ea3e3375 | |||
| ef47145135 | |||
| 43a9ee7368 | |||
| 6646e0c46c | |||
| 535dbb2e37 | |||
| 035953c7f5 | |||
| 6a9ce81d46 | |||
| f2a6824632 | |||
| 594976373e | |||
| 45704f1c31 | |||
| ce57885343 | |||
| 4d143ef959 | |||
| 9a0f9a759c | |||
| 6341f00f46 | |||
| f517568251 | |||
| 1ff6d0c2cb | |||
| 5e28039573 | |||
|
|
d7757bee0d | ||
| 6b18511708 | |||
| 4a3e0791d3 | |||
| 7c25d3f6c3 | |||
| 8ef38674d7 | |||
| e84cbf1d76 | |||
| 14f622d252 | |||
| 8bb2bfacdc | |||
| 191c4b1331 | |||
| 7bed2b977e | |||
| b6c09b2b37 | |||
|
|
1bd5251dc0 | ||
| ecf1b6b600 | |||
| 22cca82967 | |||
| cd66e42b1a | |||
| d887fa1b50 | |||
| 55870ca08a | |||
| 2ce1d49386 | |||
| a0226ccbcd | |||
| de7c14ec62 | |||
| 0c2cfd6d9a | |||
| 4ca78b9a91 | |||
| 8219c2d2ed | |||
| 9f22ce949c | |||
| d76c21c54b | |||
| 30c5cee81a | |||
| e2d0ac6d89 | |||
| 3578a65d6e | |||
| c8331b800b | |||
| 1e7dc18c21 | |||
| 046da1868e | |||
| ef7068ebd2 | |||
| 0525667032 | |||
| 6198ca02da | |||
| 4d4fd90fc6 | |||
| acfc4d710b | |||
| 4fd12f4d73 | |||
| 9a8bb9f94b | |||
| 170f758bc9 | |||
| 8b7d563fac | |||
| 6f9e0cdd8f | |||
| 0a3af7a0c0 | |||
| c90a2facac | |||
| 92d56bddab | |||
| a3bab2da47 | |||
| d51a3ac1f7 | |||
| 04774bddc3 | |||
| 770f1532da | |||
| d09872c2f3 | |||
| e77369cd25 | |||
| 69897a208c | |||
| 1f5c5ac66e | |||
| 3a7f8f09cb | |||
| 77d2b9e323 | |||
| d56c271cc4 | |||
| b4aecf5d0c | |||
| e55e23c845 | |||
| e2977dbbc4 | |||
| 8ad94ffeff | |||
| c94ff04dcf | |||
| 65f10ca22f | |||
| a1127b3bc0 | |||
| 81c16d1a3d | |||
| b1b4c82457 | |||
| 515b22b103 | |||
| c200165057 | |||
| 64c30893d5 | |||
| 98b8dce5fd | |||
| 0d9b7b6edf | |||
| b72bb1fa87 | |||
| d85131266c | |||
| 22da275f5b | |||
| f6d65b9e33 | |||
| ebc07becd0 | |||
| 024f2c2369 | |||
| 2b93fb684b | |||
| b2daf6bf65 | |||
| 3ee0f553e9 | |||
| f206da8278 | |||
| edbaeb37f5 | |||
| 46847833d0 | |||
| 4303a62b1b | |||
| d6d5babf81 | |||
| 8e5b10bda3 | |||
| 8e54ee987c | |||
| 929b30ce73 | |||
| c085fa7066 | |||
| 783e71f189 | |||
| ae1ffd313c | |||
| 122c0b5f64 | |||
| 21e496f22e | |||
| d92b3039e2 | |||
| ea57812191 | |||
| d72238df45 | |||
| 55aab8d86d | |||
| f8d4d9e4cf | |||
| 90afa6446c | |||
| 5e468c548a | |||
| 48f4521ef6 | |||
| ccd48cecfb | |||
| 0757638b2e | |||
| 68cb547d5f | |||
| 1f7c494d82 | |||
|
|
8e58783964 | ||
| bfdc0639b6 | |||
| 337a7d87e4 | |||
| 38c062220c | |||
| f639acec86 | |||
| 02ba38a01a | |||
| ea8487b14c | |||
|
|
f0b613865b | ||
| b142f37045 | |||
| 45eeb3c045 | |||
| ab99d972cd | |||
| 08562a12a2 | |||
| d7e62bbfa1 | |||
| 5829c48995 | |||
| cd133fc278 | |||
| 8a2a4d1a84 | |||
|
|
a225b98432 | ||
| 1acd50b3f3 | |||
| 5279fe0ba7 | |||
| a73f7d86a9 | |||
| 5fe7e4b43d | |||
| d50d666fb2 | |||
| 86229586f1 | |||
| 2947dea3dd | |||
| 264534ff2c | |||
| 82655592d7 | |||
|
|
85f90e8ce6 | ||
| 450ae37f05 | |||
| 07d0eff75b | |||
| 8697bea0d3 | |||
| a06839fe20 | |||
| 6542113a21 | |||
| 63d04b8c75 | |||
| 71b409a970 | |||
| e0bcc720cc | |||
| 8bcabd055b | |||
| 94597476ac | |||
| a5172d4b5a | |||
| ee79ea55db | |||
| 2230c2b632 | |||
| 9b231554ef | |||
| ccc499359b | |||
| c5ba0dd8a2 | |||
| 3811979f7e | |||
| fb17b7e3a1 | |||
| 6ea79b8b28 | |||
| 037e360e3d | |||
| 3e4a995d5a | |||
| 9d7056184a | |||
| 8aad54b2eb | |||
| 9639dc0e19 | |||
|
|
1f816c4c09 | ||
| d88c3d812e | |||
| de3f060e8b | |||
| 2c740726e2 | |||
| 01fcadf7c9 | |||
| 21378014c4 | |||
| 765e3d7d1a | |||
| 2bd77e5830 | |||
| b5c61af33c | |||
| ac7df862c1 | |||
| ae30e8c740 | |||
| db4cd40e35 | |||
| 592cdc3e17 | |||
|
|
9a84276abf | ||
| 1c70d6381b | |||
| 556da39be8 | |||
| 59c8d02c7d | |||
| 3b0b53d1b5 | |||
| 996cbfb279 | |||
| e47ad14cb1 | |||
| 8921647180 | |||
|
|
2d7933e715 | ||
| cffe463779 | |||
| 2a0e7c090d | |||
| eab8ed9551 | |||
|
|
e9c3b5d135 | ||
| 59076d4750 | |||
| 8aa84d22a8 | |||
| cfb26034b1 | |||
| 953980ee47 | |||
| 994198517a | |||
| 98728b2eb8 | |||
| 6498606e69 | |||
|
|
d17ba4d785 | ||
| e4eeed3559 | |||
| b100204b37 | |||
| 82ff3e3d0a | |||
| 0b2223bce0 | |||
| a43b723b09 | |||
| 96551f49ca | |||
| 8e32d37985 | |||
| d1da238ddc | |||
| 7260a2be21 | |||
| 7562d50e58 | |||
| e77ae8763b | |||
| a0e51c75fe | |||
| 6021a5e6e2 | |||
| e50e222955 | |||
| 531dd665c9 | |||
| a79c0a1a9b | |||
| 9ef144c304 | |||
| 5402af8df7 | |||
| 99802125dc | |||
| 705647cd3b | |||
| 0ea2eeab7f | |||
| 727cde1352 | |||
| 6ef6358cbb | |||
| 6acb303ac9 | |||
| a80e5492b8 | |||
| 4358b1a520 | |||
| ad1a7c22a6 | |||
| 2f3af23e6d | |||
| 89a26d294d | |||
| f83faeacac | |||
| fb7c27c205 | |||
| 3f958c7083 | |||
| 60b6689318 | |||
| ba94e81367 | |||
| 89c8c68b88 | |||
| e78ae7e4de | |||
| f87cadd3ce | |||
| 1631e149ea | |||
| d84f585bff | |||
| 7e9091b341 | |||
| 7020d3e198 | |||
| 9d8e0ded8f | |||
| 090e8fa160 | |||
| 83746675e7 | |||
| 74d73d76cd | |||
| 6bfedde66d | |||
| 554bee4040 | |||
| a1005adf04 | |||
| cbed47d825 | |||
| abb7da896b | |||
| e62a69ac45 | |||
| 769285736b | |||
| 8d2eaa94bd | |||
| a31143e0e8 | |||
| 584551f764 | |||
| 8b60a65bbd | |||
| c13df7c25b | |||
| ad30ba776c | |||
| de3451993f | |||
| fde9b49f39 | |||
| cff0e9442c | |||
| 5cb57d89de | |||
| fadcbaa1bb | |||
| 911554f6df | |||
| 77b525d955 | |||
| b872a2bb53 | |||
| 818444d4f4 | |||
| 63e16e05aa | |||
| 06743894a3 | |||
| 2d665235c8 | |||
| 72311a2801 | |||
| d7ba290ed3 | |||
| e0d2984bae | |||
| ecdbe8d014 | |||
| 7d57e320b8 | |||
| cf16b729f6 | |||
| 366c5c91aa | |||
| 173cf2985e | |||
| 0bdba73f25 | |||
| 24d25e69ad | |||
| d3e6297503 | |||
| 76b5f15115 | |||
| cfa92b637a | |||
| f07e75e508 | |||
| 4220300731 | |||
|
|
43b464866f | ||
| 7bf5dbb4f3 | |||
| 9fe8453898 | |||
| b421cf261f | |||
| 75d28763ee | |||
| 25533fa8bc | |||
| 04294e6cbe | |||
| f0550ba6b3 | |||
| 88d0733d95 | |||
| 74633e155a | |||
| 7d8d7a8c6f | |||
|
|
32956578b2 | ||
| 4efdf7606c | |||
| a61644861b | |||
| e60570e380 | |||
| ad160cb23e | |||
| 73f58ced9a | |||
| 36ca82c1b4 | |||
| acd46f4724 | |||
| 370ff99134 | |||
| aa317ee2f5 | |||
| 44600b5657 | |||
| ea45316a32 | |||
| 6cd13022f1 | |||
| 91ff2f7550 | |||
| 483b5b090d | |||
| 6087931c58 | |||
| 9014fd8911 | |||
| 76f7f51d80 | |||
| 0c4902e01e | |||
| 175fb089cd | |||
| 7b8a4a38b3 | |||
| ebf920ed12 | |||
| bb8591f5e5 | |||
| b8573e1f1f | |||
| dacc1e5ad8 | |||
| 8cc64e32dd | |||
| 1d294cc3b1 | |||
| f9da2e4391 | |||
| 3b78079cd2 | |||
| 07a0a1be48 | |||
| 837f95e571 | |||
|
|
909d818caa | ||
|
|
355ceebbd7 | ||
| 6ae1370709 | |||
|
|
93b5d8b8b4 | ||
|
|
be461a15a9 | ||
| c239f35382 | |||
| 49d57af719 | |||
|
|
19fc0fdc51 | ||
| c1fd4fa24c | |||
| 7239b22759 | |||
| f5fa94ae95 | |||
|
|
b679ea035d | ||
| 49bbca8faa | |||
| 8b86cd5e63 | |||
| 698e3ffd81 | |||
|
|
c2284dcee5 | ||
| b68c9edc3e | |||
| 650365997a | |||
| 3279404595 | |||
| d32a94dccf | |||
| 80d846f247 | |||
| eadcbe336d | |||
| 474d0f075f | |||
| 2d6a41e19f | |||
| 1f24944417 | |||
| 4ab3409e54 | |||
| c3ad146303 | |||
| 745cd304fb | |||
| e6efefd1fd | |||
| 1350404c58 | |||
| 9cdd2274fa | |||
| cc204ad721 | |||
| 8eb1614b31 | |||
| 9c2e9627ec | |||
| 87123c526a | |||
| 7c3ebc6e35 | |||
| 6c5bf63424 | |||
| 13fd47e7d4 | |||
| fc1321584a | |||
| bab3ae16d3 | |||
| ab8498e519 | |||
| 0e480c7ad8 | |||
| 7ed8558ff0 | |||
| 4ed2f0caa9 | |||
| f275eabe1b | |||
| fe13ab1e5f | |||
| 6ed045cf94 | |||
| ef333ff142 | |||
| dac2f5240f | |||
| cebfc2fc91 | |||
| 1da865c1b2 | |||
| 2abdaaa7ce | |||
| c62142cf6b | |||
| 7c1820b6cd | |||
| a24af95d24 | |||
| 1326c282c8 | |||
| b7e84749f1 | |||
| 8a65158540 | |||
| a576c521a2 | |||
| 736a387a71 | |||
| 090205c372 | |||
| fda0bddc8f | |||
| 292b18468d | |||
| 47aab245fc | |||
| 39bd601825 | |||
| b744adeb13 | |||
| 7b70f9fc99 | |||
|
|
0723f751b3 | ||
| 1fd8617a12 | |||
|
|
2fec8fcef4 | ||
|
|
51a48afa71 | ||
|
|
76919faca7 | ||
|
|
9bcbeaf1a5 | ||
| d0de121721 | |||
| 957e2db3d0 | |||
| fb0be5549d | |||
| 8a9132d557 | |||
| 04d10435c2 | |||
| 92543e10fa | |||
| cd427dcbf3 | |||
|
|
ddb5e0285b | ||
| 75610a4559 | |||
| b8f7a45f61 | |||
|
|
37d5ce719e | ||
| ef9053aa7e | |||
| 018fcb7afb | |||
| 5cc9a67152 | |||
| 54895f1d0a | |||
| 91dfecf882 | |||
| 2f09e227d1 | |||
| 5d0463836e | |||
|
|
fb6499cb35 | ||
| 0bbfb58e67 | |||
|
|
fcd780a7d3 | ||
| 4f4d1e7580 | |||
| 6e2a8e0a12 | |||
| 817b4b36c7 | |||
|
|
0ba89cbb9e | ||
| 4e3e7864be | |||
| 6f51eaa298 | |||
| 39bd87e868 | |||
| 18443aab60 | |||
| b88ea7aa3c | |||
| 6a6f6e6062 | |||
| 5839dbcd6b | |||
| b46f45569e | |||
| 5cdc5af8cd | |||
| 4f38a9f3ff | |||
| 9c83695187 | |||
| f9be534101 | |||
| 58ab48ac15 | |||
| f34e93192d | |||
| 31106f2b13 | |||
| 468cc54cf5 | |||
| 728a38c55c | |||
|
|
b2b23b0e3b | ||
| 167dd11548 | |||
| 03fdbf2604 | |||
| edbdec8370 | |||
| 8f1c9f9471 | |||
| d35d16943d | |||
| 3ac4270dee | |||
| 90777e08ff | |||
| b47d1262ac | |||
| e28081a7c5 | |||
| 5f7d6c1488 | |||
| 59385e11be | |||
|
|
a668d88791 | ||
| e62bd7c5a6 | |||
| 1ad3d2f187 | |||
| bf06af14ed | |||
|
|
805c96f260 | ||
| 8ccba2f6d5 | |||
| 2e9f01d3ee | |||
| d1dcdd4f25 | |||
| 60958d1403 | |||
| 5530b14f36 | |||
| 64c9942ee1 | |||
| bc1437dac4 | |||
| 1d9576e838 | |||
| 8b275a5df4 | |||
| 40d9334dcf | |||
| 98c0242819 | |||
| a2fb03f9b8 | |||
| 98815ac5c3 | |||
| 073dd20c96 | |||
| 23af9085a9 | |||
| bcaec6b6ee | |||
| 4063bea922 | |||
| 9f864b3407 | |||
| 01ac598e39 | |||
| 77a0d3af36 | |||
| 8d34bbea47 | |||
| be18e98001 | |||
| 754e0f98f9 | |||
| 07f893b6a1 | |||
|
|
c1497ec44e | ||
| 55d4784fe2 | |||
| f26e8bc520 | |||
| 7b5f1a4253 | |||
| 1058fb7e1f | |||
| 0f1b95cdfc | |||
| 8ea16fcd85 | |||
| b4b9496980 | |||
| 8dfd26361f | |||
| cb5bd32b86 | |||
| 2584330d40 | |||
| ebe6333ac9 | |||
| 534892280e | |||
| df05cf69cf | |||
| 2f782cf6a2 | |||
| 6f483c17e6 | |||
| e64610a2dc | |||
|
|
7673a16779 | ||
| d73fe4b29c | |||
| 2c61be084b | |||
| fe5f8d1997 | |||
| 2653291ded | |||
| 417f91a2e8 | |||
|
|
08625e85bb | ||
| c554c19a12 | |||
| d7d08f2f12 | |||
|
|
bafe45a2f9 | ||
| a11d24723d | |||
| 3b858476f1 | |||
| 5560b68ac1 | |||
| 8bfd381363 | |||
| c6cfe2a22c | |||
| 4ed274dedc | |||
|
|
283c815de7 | ||
| c72c1bc889 | |||
| 6e61a535ca | |||
| c1f69ea1c7 | |||
| 984599c56f | |||
| 038bb31ec3 | |||
| 1ac541d16e | |||
| ecaa0e99c5 | |||
| 666ebeef0d | |||
| b39a936fa4 | |||
| d434dce568 | |||
| 6acb390133 | |||
| 3c6f3c50c4 | |||
| c52e707421 | |||
| 5fb998c221 | |||
| a0989ea833 | |||
| 5e565c06a0 | |||
| 69b96aa5fa | |||
| bce9de1494 | |||
| 3de7928be7 | |||
| 41630ef01a | |||
| bf29cb1a4d | |||
| 8f79a4ab86 | |||
| 0ad933c5ad | |||
| 5ed9470d83 | |||
| cac468f454 | |||
| f0f9dcf4de | |||
| 3e0e84a4f6 | |||
| ef8080b420 | |||
| b5fab1fb10 | |||
| c3f019d4ff | |||
| 701f172276 | |||
| 9e8c736cb4 | |||
| c8589d750c | |||
| 5bb20a01de | |||
| 6e4bf9da3e | |||
| c21ddb5c63 | |||
| 431295cec9 | |||
| 180cb84b2c | |||
| 66b5f322d9 | |||
| f00dc248bd | |||
| dbba5db9f7 | |||
| 3a8b799df6 | |||
| 0b99a4ae74 | |||
| 99b77d347a | |||
| 8235a88ecc | |||
| 564ba30f91 | |||
| aa8535d513 | |||
| a02ef2575b | |||
| a0be16c0fa | |||
| 548d87e339 | |||
| c704aa0817 | |||
| c6a060fde5 | |||
| 762e88cc44 | |||
| b7f671d1d5 | |||
| 48706d01f9 | |||
| fb53354956 | |||
| 5995147054 | |||
| fed9f458d1 | |||
| 7987564401 | |||
| 90ae21fb8b | |||
| 56a78d174d | |||
| 37da947b90 | |||
| f23e272027 | |||
| 10afc0a2d5 | |||
| f59c8ea533 | |||
| 4153ea7431 | |||
| 2c73577798 | |||
| 0b5c53ef7e | |||
| 0fca0d54f8 | |||
| 3da0c5b2b6 | |||
| d8519bc1c3 | |||
| 33a4a799c5 | |||
| 358a021ba6 | |||
| 6dba9c25b6 | |||
|
|
1f724c802b | ||
|
|
67e3dd0035 | ||
|
|
de657829fd | ||
| a2c27134a8 | |||
| 66c60ec10e | |||
| 867b39d8e1 | |||
| 1c8997d44a | |||
| 88b5112e30 | |||
| 3874b6a25a | |||
|
|
8ba6587c57 | ||
| 3ebe36f785 | |||
|
|
34ed0b96d3 | ||
| ab353d2268 | |||
|
|
fd6f013480 | ||
| 4d0b7bc127 | |||
| ce917b227f | |||
| dec1bb04e8 | |||
|
|
a1093c17bc | ||
| 8110fbf701 | |||
| cf502ebf05 | |||
| 7c7837b967 | |||
| 3bfc1cacb0 | |||
| cd2ea26608 | |||
| dcf8159d1c | |||
|
|
1bdab80b5d | ||
| 241c4dc600 | |||
| 18e93d2b24 | |||
| 084cf6b761 | |||
| 47ddf5f4e6 | |||
| 325321f5d4 | |||
| ecbeca3d35 | |||
| 862b434c72 | |||
| 6376ed3b7b | |||
| 42e40d1718 | |||
| 1c1cc12058 | |||
| e648b88a74 | |||
|
|
6fea46f7c8 | ||
| a06e5a6e55 | |||
| 85bf429a08 | |||
| dd6ba45cdd | |||
| ab967efa64 | |||
| 369505e1a0 | |||
| 86d858a0fb | |||
| d1f5158276 | |||
|
|
db83b0f78c | ||
| 24fcc5a0c6 | |||
|
|
9cb3d474aa | ||
| 0adfebfad6 | |||
| 66c4225aa3 | |||
| 6ddef9ffda | |||
| 27a1b22e6f | |||
| f9c18cb225 | |||
| b97733328a | |||
|
|
2fe17aefd9 | ||
| acddca54cd | |||
| 7d80fb31ce | |||
|
|
8ac1d78053 | ||
| 468d6d7752 | |||
| f49d789411 | |||
| 1f56115fbb | |||
| 20d277102e | |||
| 47b4036f09 | |||
|
|
ee9e154fec | ||
| 85256b4fb6 | |||
|
|
16be671f1d | ||
| af880115ab | |||
| e64ac8f616 | |||
| a7d4206b77 | |||
| 5a80690404 | |||
| 9b0d71d4ac | |||
| 729f77d8db | |||
| e89f96aa2d | |||
|
|
f05f81cace | ||
| f4883ee708 | |||
| 043fb739d9 | |||
| b19aa8702b | |||
| f4e0744879 | |||
|
|
d7c822f86d | ||
| c8f8e217e5 | |||
|
|
bfec7f1fe8 | ||
| 21fce1f618 | |||
| b5987b57ad | |||
| e8c1cb08a7 | |||
| 0de3a16898 | |||
| 278bd7f38e | |||
| 4a3b9db324 | |||
| b3e8e96875 | |||
| f5e50c6d76 | |||
| c551c2ee1a | |||
| 3fb8406e7b | |||
| 50d12407c9 | |||
| 17931bb0ea | |||
| 6d30940920 | |||
| 3a4c985baf | |||
|
|
960d8b6cb8 | ||
| 9b7e9d4ffa | |||
| c1a646c0d7 | |||
| 48ef0e7a65 | |||
| 8dff306a91 | |||
| a935acbc95 | |||
| b1f9c99eb1 | |||
| 0851f749c3 | |||
| 3a7d9f84c7 | |||
| b43b35ccab | |||
| 5fc6eacc53 | |||
| bd782362e8 | |||
| 32151a176f | |||
| f7c88d2086 | |||
| 1eb76f2b90 | |||
| 226b3e049d | |||
|
|
7f0e9851cd | ||
| 15df77940e | |||
| 9781516552 | |||
| a23264a542 | |||
| 0e7845985a | |||
| 93efe45347 | |||
| a46f824e1e | |||
|
|
0de9f036bc | ||
| 275f2515d6 | |||
| b4604928ec | |||
| 5a79b4021a | |||
| 280fd38039 | |||
|
|
b032364616 | ||
| a430aaee97 | |||
| f4ee2ca3b9 | |||
| 92b9212b31 | |||
| 73656e60ff | |||
| 401329d80c | |||
|
|
6131970724 | ||
| 85dcc4b78a | |||
| 34a1bf7e28 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -196,3 +196,4 @@ plugins/goedge-happy
|
||||
/plugins/choose-linux-python
|
||||
*.md5
|
||||
/bak
|
||||
*.tmp
|
||||
|
||||
@@ -108,11 +108,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
|
||||
```
|
||||
|
||||
|
||||
### 版本更新 0.18.5
|
||||
### 版本更新 0.19.0
|
||||
|
||||
- 常规优化。
|
||||
|
||||
### JSDelivr安装地址
|
||||
### 增加在线更新支持。
|
||||
|
||||
- 初始安装
|
||||
|
||||
|
||||
4
cli.sh
4
cli.sh
@@ -19,12 +19,12 @@ fi
|
||||
mw_start_task()
|
||||
{
|
||||
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}')
|
||||
if [ "$isStart" == '' ];then
|
||||
if [ "$isStart" = '' ];then
|
||||
echo -e "starting mw-tasks... \c"
|
||||
cd $DIR && python3 panel_task.py >> ${DIR}/logs/panel_task.log 2>&1 &
|
||||
sleep 0.3
|
||||
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}')
|
||||
if [ "$isStart" == '' ];then
|
||||
if [ "$isStart" = '' ];then
|
||||
echo -e "\033[31mfailed\033[0m"
|
||||
echo '------------------------------------------------------'
|
||||
tail -n 20 $DIR/logs/panel_task.log
|
||||
|
||||
@@ -80,6 +80,7 @@ def runPanelTask():
|
||||
# 站点过期检查
|
||||
siteEdateCheck()
|
||||
|
||||
# echo "True" > /www/server/mdserver-web/logs/panel_task.lock
|
||||
lock_file = mw.getTriggerTaskLockFile()
|
||||
try:
|
||||
if os.path.exists(lock_file):
|
||||
@@ -183,7 +184,7 @@ def check502():
|
||||
verlist = [
|
||||
'52', '53', '54', '55', '56', '70',
|
||||
'71', '72', '73', '74', '80', '81',
|
||||
'82', '83', '84'
|
||||
'82', '83', '84', '85'
|
||||
]
|
||||
for ver in verlist:
|
||||
server_dir = mw.getServerDir()
|
||||
|
||||
@@ -223,14 +223,14 @@ def mwcli(mw_input=0):
|
||||
else:
|
||||
mw.echoInfo("二次验证已关闭!")
|
||||
elif mw_input == 27:
|
||||
cmd = 'which ufw'
|
||||
cmd = 'command -v ufw'
|
||||
run_cmd = False
|
||||
find_cmd = mw.execShell(cmd)
|
||||
if find_cmd[0].strip() != '':
|
||||
run_cmd = True
|
||||
os.system('ufw status')
|
||||
|
||||
cmd = 'which firewall-cmd'
|
||||
cmd = 'command -v firewall-cmd'
|
||||
find_cmd = mw.execShell(cmd)
|
||||
if find_cmd[0].strip() != '':
|
||||
run_cmd = True
|
||||
|
||||
@@ -606,7 +606,7 @@ def runHookDstDomain(row):
|
||||
|
||||
if mw.isAppleSystem():
|
||||
user = getRunUser()
|
||||
cmd += "source /Users/"+user+"/.zshrc\n"
|
||||
cmd += ". /Users/"+user+"/.zshrc\n"
|
||||
|
||||
cmd_data = getDnsapiData(row['dnsapi_id'])
|
||||
# print(cmd_data)
|
||||
|
||||
@@ -13,7 +13,7 @@ VERSION=$2
|
||||
# acme.sh --uninstall
|
||||
|
||||
|
||||
# source /Users/xxx/.zshrc
|
||||
# . /Users/xxx/.zshrc
|
||||
|
||||
# https://github.com/acmesh-official/acme.sh/wiki/dnsapi
|
||||
# https://docs.dnspod.com/api-legacy/domains.html#get-the-domain-list
|
||||
@@ -24,7 +24,7 @@ VERSION=$2
|
||||
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
# pip install cloudflare
|
||||
@@ -47,7 +47,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -122,7 +122,7 @@ def openPort():
|
||||
return True
|
||||
|
||||
def status():
|
||||
cmd = "ps aux|grep alist |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
cmd = "ps -ef|grep alist |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -16,16 +16,16 @@ sysArch=`arch`
|
||||
sysName=`uname`
|
||||
|
||||
ALIST_ARCH_NAME=amd64
|
||||
if [ "$sysArch" == "arm64" ];then
|
||||
if [ "$sysArch" = "arm64" ];then
|
||||
ALIST_ARCH_NAME=arm64
|
||||
elif [ "$sysArch" == "x86_64" ]; then
|
||||
elif [ "$sysArch" = "x86_64" ]; then
|
||||
ALIST_ARCH_NAME=amd64
|
||||
elif [ "$sysArch" == "aarch64" ]; then
|
||||
elif [ "$sysArch" = "aarch64" ]; then
|
||||
ALIST_ARCH_NAME=arm64
|
||||
fi
|
||||
|
||||
ALIST_NAME=linux
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
if [ "$sysName" = "Darwin" ];then
|
||||
ALIST_NAME=darwin
|
||||
fi
|
||||
|
||||
@@ -86,7 +86,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -27,7 +27,7 @@ else
|
||||
fi
|
||||
|
||||
NGINX_IDS=`ps -ef|grep nginx | grep -v grep| awk '{print $2}'`
|
||||
if [ "$NGINX_IDS" == "" ];then
|
||||
if [ "$NGINX_IDS" = "" ];then
|
||||
ps -ef|grep nginx| grep -v grep| awk '{print $2}' | xargs kill -9
|
||||
systemctl start "$service_name"
|
||||
echo "OpenResty未运行,正在启动服务..."
|
||||
|
||||
@@ -174,7 +174,7 @@ def initDreplace():
|
||||
|
||||
|
||||
def status():
|
||||
cmd = "ps -ef|grep 'httpd/bin/httpd' |grep -v grep | grep -v python | awk '{print $2}'"
|
||||
cmd = "ps -ef|grep 'httpd' |grep -v grep | grep -v python | awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -38,7 +38,7 @@ else
|
||||
useradd -g www -s /bin/bash www
|
||||
fi
|
||||
|
||||
if [ "${action}" == "upgrade" ];then
|
||||
if [ "${action}" = "upgrade" ];then
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
|
||||
echo "${VERSION}" > $serverPath/apache/version.pl
|
||||
@@ -53,12 +53,12 @@ if [ "${action}" == "upgrade" ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
if [ "${2}" = "" ];then
|
||||
echo '缺少安装脚本版本...'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${action}" == "uninstall" ];then
|
||||
if [ "${action}" = "uninstall" ];then
|
||||
if [ -f /usr/lib/systemd/system/httpd.service ] || [ -f /lib/systemd/system/httpd.service ];then
|
||||
systemctl stop httpd
|
||||
rm -rf /usr/systemd/system/httpd.service
|
||||
@@ -75,7 +75,7 @@ fi
|
||||
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
|
||||
if [ "${action}" == "install" ] && [ -d $serverPath/apache ];then
|
||||
if [ "${action}" = "install" ] && [ -d $serverPath/apache ];then
|
||||
echo "${VERSION}" > $serverPath/apache/version.pl
|
||||
|
||||
mkdir -p $serverPath/web_conf/php/conf
|
||||
|
||||
@@ -14,12 +14,12 @@ sysName=`uname`
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
VERSION=2.4.66
|
||||
VERSION=2.4.68
|
||||
apacheDir=${serverPath}/source/apache
|
||||
|
||||
Install_App()
|
||||
{
|
||||
if [ "${action}" == "install" ];then
|
||||
if [ "${action}" = "install" ];then
|
||||
if [ -d $serverPath/apache ];then
|
||||
exit 0
|
||||
fi
|
||||
@@ -71,7 +71,7 @@ Install_App()
|
||||
cd ${apacheDir} && tar -jxf apr-${APR_VERSION}.tar.bz2
|
||||
cd ${apacheDir}/apr-${APR_VERSION} && ./configure --prefix=${serverPath}/apache/apr
|
||||
make -j${cpuCore} && make install
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
# 检查 APR 配置文件
|
||||
APR_CONFIG=$(find ${serverPath}/apache/apr -name "apr-*config" | head -1)
|
||||
if [ -z "$APR_CONFIG" ];then
|
||||
@@ -90,7 +90,7 @@ Install_App()
|
||||
cd ${apacheDir} && tar -jxf apr-util-${APR_UTIL_VERSION}.tar.bz2
|
||||
cd ${apacheDir}/apr-util-${APR_UTIL_VERSION} && ./configure --prefix=${serverPath}/apache/apr-util --with-apr=${serverPath}/apache/apr
|
||||
make -j${cpuCore} && make install
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
# 检查 APR-util 配置文件
|
||||
APU_CONFIG=$(find ${serverPath}/apache/apr-util -name "apu-*config" | head -1)
|
||||
if [ -z "$APU_CONFIG" ];then
|
||||
@@ -163,9 +163,9 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == "install" ];then
|
||||
if [ "${1}" = "install" ];then
|
||||
Install_App
|
||||
elif [ "${1}" == "upgrade" ];then
|
||||
elif [ "${1}" = "upgrade" ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -24,7 +24,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App $2
|
||||
else
|
||||
Uninstall_App $2
|
||||
|
||||
@@ -27,7 +27,7 @@ else
|
||||
fi
|
||||
|
||||
NGINX_IDS=`ps -ef|grep caddy | grep -v grep| awk '{print $2}'`
|
||||
if [ "$NGINX_IDS" == "" ];then
|
||||
if [ "$NGINX_IDS" = "" ];then
|
||||
ps -ef|grep caddy| grep -v grep| awk '{print $2}' | xargs kill -9
|
||||
systemctl start "$service_name"
|
||||
echo "caddy未运行,正在启动服务..."
|
||||
|
||||
@@ -109,7 +109,7 @@ def initDreplace():
|
||||
caddy_file = getConf()
|
||||
if not os.path.exists(caddy_file):
|
||||
caddy_file_tpl = getConfTpl()
|
||||
content = mw.readFile(systemServiceTpl)
|
||||
content = mw.readFile(caddy_file_tpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
mw.writeFile(caddy_file, content)
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ After=network.target network-online.target
|
||||
Requires=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
User=caddy
|
||||
Group=caddy
|
||||
Type=simple
|
||||
User=www
|
||||
Group=www
|
||||
ExecStart={$SERVER_PATH}/caddy/bin/caddy run --environ --config {$SERVER_PATH}/caddy/Caddyfile
|
||||
ExecReload={$SERVER_PATH}/caddy/bin/caddy reload --config {$SERVER_PATH}/caddy/Caddyfile --force
|
||||
TimeoutStopSec=5s
|
||||
|
||||
@@ -3,7 +3,7 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/hom
|
||||
export PATH
|
||||
|
||||
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/caddy && bash install.sh install 1.21.4
|
||||
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 1.21.4
|
||||
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 2.11
|
||||
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 1.29.2
|
||||
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh upgrade 1.29.2
|
||||
|
||||
@@ -33,7 +33,7 @@ else
|
||||
useradd -g www -s /bin/bash www
|
||||
fi
|
||||
|
||||
if [ "${action}" == "upgrade" ];then
|
||||
if [ "${action}" = "upgrade" ];then
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
|
||||
echo "${VERSION}" > $serverPath/caddy/version.pl
|
||||
@@ -45,12 +45,12 @@ if [ "${action}" == "upgrade" ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
if [ "${2}" = "" ];then
|
||||
echo '缺少安装脚本版本...'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${action}" == "uninstall" ];then
|
||||
if [ "${action}" = "uninstall" ];then
|
||||
if [ -f /usr/lib/systemd/system/caddy.service ] || [ -f /lib/systemd/system/caddy.service ];then
|
||||
systemctl stop caddy
|
||||
rm -rf /usr/systemd/system/caddy.service
|
||||
@@ -67,7 +67,7 @@ fi
|
||||
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
|
||||
if [ "${action}" == "install" ] && [ -d $serverPath/caddy ];then
|
||||
if [ "${action}" = "install" ] && [ -d $serverPath/caddy ];then
|
||||
echo "${VERSION}" > $serverPath/caddy/version.pl
|
||||
|
||||
#初始化
|
||||
|
||||
@@ -30,6 +30,7 @@ case $(uname -m) in
|
||||
x86_64) ARCH_NAME="amd64" ;;
|
||||
arm) ARCH_NAME="arm64" ;;
|
||||
arm64) ARCH_NAME="arm64" ;;
|
||||
aarch64) ARCH_NAME="arm64" ;;
|
||||
esac
|
||||
|
||||
VERSION=2.11.2
|
||||
@@ -38,7 +39,7 @@ caddyDir=${serverPath}/source/caddy
|
||||
|
||||
Install_App()
|
||||
{
|
||||
if [ "${action}" == "install" ];then
|
||||
if [ "${action}" = "install" ];then
|
||||
if [ -d $serverPath/caddy ];then
|
||||
exit 0
|
||||
fi
|
||||
@@ -59,7 +60,7 @@ Install_App()
|
||||
|
||||
mkdir -p cd $serverPath/source/caddy/caddy
|
||||
cd $serverPath/source/caddy/caddy && tar -zxvf ${caddyDir}/$FILE_NAME
|
||||
if [ "$OSNAME" == "mac" ];then
|
||||
if [ "$OSNAME" = "mac" ];then
|
||||
xattr -cr caddy
|
||||
fi
|
||||
|
||||
@@ -78,9 +79,9 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == "install" ];then
|
||||
if [ "${1}" = "install" ];then
|
||||
Install_App
|
||||
elif [ "${1}" == "upgrade" ];then
|
||||
elif [ "${1}" = "upgrade" ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -142,6 +142,7 @@ def initConf():
|
||||
"/www/server/rsyncd",
|
||||
"/www/server/acme_pandominassl_apply",
|
||||
"/www/server/sphinx/index",
|
||||
"/www/server/manticoresearch",
|
||||
"/www/server/mongodb/logs",
|
||||
"/www/server/php/53/var/log",
|
||||
"/www/server/php/54/var/log",
|
||||
@@ -165,6 +166,7 @@ def initConf():
|
||||
"/www/server/alist/data/log",
|
||||
"/www/server/dztasks/logs",
|
||||
"/www/server/rsyncd/lsyncd.log",
|
||||
"/www/server/mdserver-web/logs",
|
||||
]
|
||||
for i in clogcom:
|
||||
if os.path.exists(i):
|
||||
|
||||
@@ -13,7 +13,7 @@ serverPath=$(dirname "$rootPath")
|
||||
VERSION=$2
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Uninstall_app()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_app
|
||||
else
|
||||
Uninstall_app
|
||||
|
||||
@@ -99,7 +99,7 @@ def readConfigTpl():
|
||||
|
||||
def status():
|
||||
data = mw.execShell(
|
||||
"ps aux|grep cloudreve |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
|
||||
"ps -ef|grep cloudreve |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
|
||||
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -16,16 +16,16 @@ sysArch=`arch`
|
||||
sysName=`uname`
|
||||
|
||||
ALIST_ARCH_NAME=amd64
|
||||
if [ "$sysArch" == "arm64" ];then
|
||||
if [ "$sysArch" = "arm64" ];then
|
||||
ALIST_ARCH_NAME=arm64
|
||||
elif [ "$sysArch" == "x86_64" ]; then
|
||||
elif [ "$sysArch" = "x86_64" ]; then
|
||||
ALIST_ARCH_NAME=amd64
|
||||
elif [ "$sysArch" == "aarch64" ]; then
|
||||
elif [ "$sysArch" = "aarch64" ]; then
|
||||
ALIST_ARCH_NAME=aarch64
|
||||
fi
|
||||
|
||||
ALIST_NAME=linux
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
if [ "$sysName" = "Darwin" ];then
|
||||
ALIST_NAME=darwin
|
||||
fi
|
||||
|
||||
@@ -83,7 +83,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -15,7 +15,7 @@ from pprint import pprint
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import mw
|
||||
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ curPath=`pwd`
|
||||
# bash plugins/cryptocurrency_trade/ccxt/public_data/data.sh
|
||||
|
||||
if [ -f ${curPath}/bin/activate ];then
|
||||
source ${curPath}/bin/activate
|
||||
. ${curPath}/bin/activate
|
||||
fi
|
||||
|
||||
python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long
|
||||
|
||||
@@ -11,7 +11,7 @@ from decimal import Decimal
|
||||
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
|
||||
import common
|
||||
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/func_test.py run
|
||||
|
||||
# common.notifyMsg("任务开始")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/gate_100.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/gate_100.py long
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from pprint import pprint
|
||||
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
|
||||
import common
|
||||
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/hammer_robot.py run
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/macd_kdj.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/macd_kdj.py long
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/momentun_trade.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/momentun_trade.py long
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/notify_demo.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/notify_demo.py long
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_buy_open
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_buy_close
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_macd_trade.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_macd_trade.py long
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_buy_open
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_buy_close
|
||||
|
||||
@@ -11,7 +11,7 @@ from pprint import pprint
|
||||
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
|
||||
import common
|
||||
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/rsi_robot.py run
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cd /www/server/mdserver-web && source bin/activate
|
||||
# cd /www/server/mdserver-web && . bin/activate
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/vega_trade.py run
|
||||
# python3 plugins/cryptocurrency_trade/ccxt/strategy/vega_trade.py long
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ pip install git+https://github.com/catalyst-team/catalyst@master --upgrade
|
||||
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
|
||||
|
||||
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && source bin/activate
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && . bin/activate
|
||||
|
||||
python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
|
||||
'''
|
||||
|
||||
@@ -5,7 +5,7 @@ pip install git+https://github.com/catalyst-team/catalyst@master --upgrade
|
||||
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
|
||||
|
||||
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && source bin/activate
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && . bin/activate
|
||||
|
||||
python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
|
||||
'''
|
||||
|
||||
@@ -9,10 +9,10 @@ from catalyst import run_algorithm
|
||||
from catalyst.api import order, record, symbol
|
||||
|
||||
'''
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && source bin/activate
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && / bin/activate
|
||||
|
||||
|
||||
cd /www/server/mdserver-web && source bin/activate && source activate catalys
|
||||
cd /www/server/mdserver-web && . bin/activate && source activate catalys
|
||||
|
||||
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p_test.py
|
||||
catalyst ingest-exchange -x binance -i btc_usdt -f minute
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[program:{$NAME}]
|
||||
command=bash -c "cd {$RUN_ROOT} && source bin/activate && python3 {$ABS_FILE} long"
|
||||
command=bash -c "cd {$RUN_ROOT} && . bin/activate && python3 {$ABS_FILE} long"
|
||||
directory={$RUN_ROOT}
|
||||
autorestart=true
|
||||
startsecs=3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[program:{$NAME}]
|
||||
command=bash -c "cd {$RUN_ROOT} && source bin/activate && python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long"
|
||||
command=bash -c "cd {$RUN_ROOT} && . bin/activate && python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long"
|
||||
directory={$RUN_ROOT}
|
||||
autorestart=true
|
||||
startsecs=3
|
||||
|
||||
@@ -14,7 +14,7 @@ VERSION=$2
|
||||
|
||||
# pip3 install ccxt
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
pip3 install ccxt
|
||||
pip3 install pandas
|
||||
@@ -56,7 +56,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -26,7 +26,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -37,6 +37,7 @@ class nosqlMemcached():
|
||||
__DB_HOST = '127.0.0.1'
|
||||
__DB_CONN = None
|
||||
__DB_ERR = None
|
||||
__DB_STATUS = None
|
||||
|
||||
__DB_LOCAL = None
|
||||
|
||||
@@ -48,19 +49,36 @@ class nosqlMemcached():
|
||||
|
||||
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
|
||||
mem_path = "{}/memcached".format(mw.getServerDir())
|
||||
if not os.path.exists(mem_path): return False
|
||||
if not os.path.exists(mem_path):
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
if not self.__DB_LOCAL:
|
||||
if not self.__config:
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
self.__DB_PORT = int(self.__config['port'])
|
||||
try:
|
||||
self.__DB_CONN = pymemcache.client.base.PooledClient((self.__DB_HOST,self.__DB_PORT), max_pool_size=4)
|
||||
# PooledClient 是惰性连接,探测一次,服务未启动时及时返回 False
|
||||
self.__DB_CONN.version()
|
||||
self.__DB_STATUS = None
|
||||
return self.__DB_CONN
|
||||
except pymemcache.exceptions.MemcacheError:
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
except (ConnectionRefusedError, OSError):
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
except Exception:
|
||||
self.__DB_ERR = mw.getTracebackInfo()
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
|
||||
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
|
||||
def get_status(self):
|
||||
return self.__DB_STATUS
|
||||
|
||||
# 获取配置项
|
||||
def get_options(self, get=None):
|
||||
|
||||
@@ -95,11 +113,20 @@ class nosqlMemcachedCtr():
|
||||
instance = nosqlMemcached()
|
||||
return instance
|
||||
|
||||
def _connect(self, sid):
|
||||
obj = self.getInstanceBySid(sid)
|
||||
conn = obj.conn()
|
||||
if conn is False:
|
||||
if obj.get_status() == 'not_installed':
|
||||
return None, mw.returnData(False, '未安装')
|
||||
return None, mw.returnData(False, '未启动')
|
||||
return conn, None
|
||||
|
||||
def getItems(self, args):
|
||||
sid = args['sid']
|
||||
mem_instance = self.getInstanceBySid(sid).conn()
|
||||
if mem_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mem_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = {}
|
||||
m_items = mem_instance.stats('items')
|
||||
@@ -122,9 +149,9 @@ class nosqlMemcachedCtr():
|
||||
|
||||
def getKeyList(self, args):
|
||||
sid = args['sid']
|
||||
mem_instance = self.getInstanceBySid(sid).conn()
|
||||
if mem_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mem_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
|
||||
p = 1
|
||||
@@ -194,9 +221,9 @@ class nosqlMemcachedCtr():
|
||||
def delVal(self, args):
|
||||
|
||||
sid = args['sid']
|
||||
mem_instance = self.getInstanceBySid(sid).conn()
|
||||
if mem_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mem_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
key = args['key']
|
||||
mem_instance.delete(key)
|
||||
@@ -205,9 +232,9 @@ class nosqlMemcachedCtr():
|
||||
def setKv(self, args):
|
||||
|
||||
sid = args['sid']
|
||||
mem_instance = self.getInstanceBySid(sid).conn()
|
||||
if mem_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mem_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
key = args['key']
|
||||
val = args['val']
|
||||
@@ -217,9 +244,9 @@ class nosqlMemcachedCtr():
|
||||
|
||||
def clear(self, args):
|
||||
sid = args['sid']
|
||||
mem_instance = self.getInstanceBySid(sid).conn()
|
||||
if mem_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mem_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
mem_instance.flush_all()
|
||||
return mw.returnData(True,'清空成功!')
|
||||
|
||||
@@ -127,6 +127,7 @@ class nosqlMongodb():
|
||||
__DB_HOST = '127.0.0.1'
|
||||
__DB_CONN = None
|
||||
__DB_ERR = None
|
||||
__DB_STATUS = None
|
||||
|
||||
__DB_LOCAL = None
|
||||
|
||||
@@ -138,29 +139,51 @@ class nosqlMongodb():
|
||||
|
||||
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
|
||||
mgdb_path = "{}/mongodb".format(mw.getServerDir())
|
||||
if not os.path.exists(mgdb_path): return False
|
||||
if not os.path.exists(mgdb_path):
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
if not self.__DB_LOCAL:
|
||||
if not self.__config:
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
self.__DB_PORT = int(self.__config['port'])
|
||||
|
||||
auth = getConfAuth()
|
||||
port = getConfPort()
|
||||
mg_root = pSqliteDb('config').where('id=?', (1,)).getField('mg_root')
|
||||
# print(auth,self.__DB_HOST,port, self.__DB_PASS)
|
||||
try:
|
||||
if auth == 'disabled':
|
||||
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True)
|
||||
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, serverSelectionTimeoutMS=3000)
|
||||
else:
|
||||
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, username='root',password=mg_root)
|
||||
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, username='root',password=mg_root, serverSelectionTimeoutMS=3000)
|
||||
self.__DB_CONN.admin.command('ping')
|
||||
# 节点处于 recovering/startup 时 ping 仍会成功,但读写会抛 NotPrimaryError
|
||||
try:
|
||||
hello = self.__DB_CONN.admin.command('hello')
|
||||
except Exception:
|
||||
# MongoDB < 5.0 没有 hello 命令
|
||||
hello = self.__DB_CONN.admin.command('isMaster')
|
||||
if not (hello.get('isWritablePrimary') or hello.get('ismaster') or hello.get('secondary')):
|
||||
self.__DB_ERR = 'MongoDB 节点当前不是 primary 或 secondary 状态'
|
||||
return False
|
||||
self.__DB_STATUS = None
|
||||
self.__DB_ERR = None
|
||||
return self.__DB_CONN
|
||||
except pymongo.errors.ConnectionFailure:
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
except Exception as e:
|
||||
# print(e)
|
||||
self.__DB_ERR = mw.getTracebackInfo()
|
||||
except Exception:
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
|
||||
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
|
||||
def get_status(self):
|
||||
return self.__DB_STATUS
|
||||
|
||||
def get_err(self):
|
||||
return self.__DB_ERR
|
||||
|
||||
# 获取配置项
|
||||
def get_options(self, get=None):
|
||||
result = {}
|
||||
@@ -202,11 +225,23 @@ class nosqlMongodbCtr():
|
||||
instance = nosqlMongodb()
|
||||
return instance
|
||||
|
||||
def _connect(self, sid):
|
||||
obj = self.getInstanceBySid(sid)
|
||||
conn = obj.mgdb_conn()
|
||||
if conn is False:
|
||||
if obj.get_status() == 'not_installed':
|
||||
return None, mw.returnData(False, '未安装')
|
||||
err = obj.get_err()
|
||||
if err:
|
||||
return None, mw.returnData(False, err)
|
||||
return None, mw.returnData(False, '未启动')
|
||||
return conn, None
|
||||
|
||||
def getDbList(self, args):
|
||||
sid = args['sid']
|
||||
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
|
||||
if mgdb_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mgdb_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = {}
|
||||
doc_list = mgdb_instance.list_database_names()
|
||||
@@ -221,9 +256,9 @@ class nosqlMongodbCtr():
|
||||
sid = args['sid']
|
||||
name = args['name']
|
||||
|
||||
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
|
||||
if mgdb_instance is False:
|
||||
return mw.returnData(False,'无法链接.')
|
||||
mgdb_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = {}
|
||||
collections = mgdb_instance[name].list_collection_names()
|
||||
@@ -242,9 +277,9 @@ class nosqlMongodbCtr():
|
||||
if 'size' in args:
|
||||
size = args['size']
|
||||
|
||||
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
|
||||
if mgdb_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mgdb_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
db_instance = mgdb_instance[db]
|
||||
collection_instance = db_instance[collection]
|
||||
@@ -303,9 +338,9 @@ class nosqlMongodbCtr():
|
||||
db = args['db']
|
||||
collection = args['collection']
|
||||
|
||||
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
|
||||
if mgdb_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
mgdb_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
db_instance = mgdb_instance[db]
|
||||
collection_instance = db_instance[collection]
|
||||
|
||||
@@ -32,6 +32,7 @@ class nosqlRedis():
|
||||
__DB_HOST = '127.0.0.1'
|
||||
__DB_CONN = None
|
||||
__DB_ERR = None
|
||||
__DB_STATUS = None
|
||||
|
||||
__DB_LOCAL = None
|
||||
|
||||
@@ -44,9 +45,13 @@ class nosqlRedis():
|
||||
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
|
||||
redis_path = "{}/redis".format(mw.getServerDir())
|
||||
if not os.path.exists(redis_path):
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
if not self.__DB_LOCAL:
|
||||
if not self.__config:
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
self.__DB_PASS = self.__config['requirepass']
|
||||
self.__DB_PORT = int(self.__config['port'])
|
||||
|
||||
@@ -55,13 +60,20 @@ class nosqlRedis():
|
||||
redis_pool = redis.ConnectionPool(host=self.__DB_HOST, port=self.__DB_PORT, password=self.__DB_PASS, db=db_idx, socket_timeout=3)
|
||||
self.__DB_CONN = redis.Redis(connection_pool=redis_pool)
|
||||
self.__DB_CONN.ping()
|
||||
self.__DB_STATUS = None
|
||||
return self.__DB_CONN
|
||||
except redis.exceptions.ConnectionError:
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
except Exception:
|
||||
self.__DB_ERR = mw.getTracebackInfo()
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
|
||||
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
|
||||
def get_status(self):
|
||||
return self.__DB_STATUS
|
||||
|
||||
# 获取配置项
|
||||
def get_options(self, get=None):
|
||||
|
||||
@@ -112,12 +124,21 @@ class nosqlRedisCtr():
|
||||
instance = nosqlRedis()
|
||||
return instance
|
||||
|
||||
def _connect(self, sid, idx=0):
|
||||
obj = self.getInstanceBySid(sid)
|
||||
conn = obj.redis_conn(idx)
|
||||
if conn is False:
|
||||
if obj.get_status() == 'not_installed':
|
||||
return None, mw.returnData(False, '未安装')
|
||||
return None, mw.returnData(False, '未启动')
|
||||
return conn, None
|
||||
|
||||
def getList(self, args):
|
||||
|
||||
sid = args['sid']
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(0)
|
||||
if redis_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
redis_instance, err = self._connect(sid, 0)
|
||||
if err:
|
||||
return err
|
||||
|
||||
|
||||
redis_info = redis_instance.info()
|
||||
@@ -166,7 +187,9 @@ class nosqlRedisCtr():
|
||||
if 'search' in args and args['search'] != '':
|
||||
search = args['search']
|
||||
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
|
||||
redis_instance, err = self._connect(sid, idx)
|
||||
if err:
|
||||
return err
|
||||
|
||||
total = redis_instance.dbsize()
|
||||
|
||||
@@ -251,7 +274,9 @@ class nosqlRedisCtr():
|
||||
val = args["val"]
|
||||
endtime = args["endtime"]
|
||||
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
|
||||
redis_instance, err = self._connect(sid, idx)
|
||||
if err:
|
||||
return err
|
||||
|
||||
redis_info = redis_instance.info()
|
||||
if redis_info['role'] == 'slave':
|
||||
@@ -268,7 +293,9 @@ class nosqlRedisCtr():
|
||||
sid = args['sid']
|
||||
idx = args['idx']
|
||||
name = args["name"]
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
|
||||
redis_instance, err = self._connect(sid, idx)
|
||||
if err:
|
||||
return err
|
||||
|
||||
redis_info = redis_instance.info()
|
||||
if redis_info['role'] == 'slave':
|
||||
@@ -281,7 +308,9 @@ class nosqlRedisCtr():
|
||||
sid = args['sid']
|
||||
idx = args['idx']
|
||||
keys = args["keys"]
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
|
||||
redis_instance, err = self._connect(sid, idx)
|
||||
if err:
|
||||
return err
|
||||
|
||||
redis_info = redis_instance.info()
|
||||
if redis_info['role'] == 'slave':
|
||||
@@ -297,7 +326,9 @@ class nosqlRedisCtr():
|
||||
idxs = args['idxs']
|
||||
|
||||
for idx in idxs:
|
||||
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
|
||||
redis_instance, err = self._connect(sid, idx)
|
||||
if err:
|
||||
return err
|
||||
|
||||
redis_info = redis_instance.info()
|
||||
if redis_info['role'] == 'slave':
|
||||
|
||||
@@ -31,6 +31,7 @@ class nosqlMySQL():
|
||||
__DB_HOST = '127.0.0.1'
|
||||
__DB_CONN = None
|
||||
__DB_ERR = None
|
||||
__DB_STATUS = None
|
||||
__DB_SOCKET = None
|
||||
|
||||
__DB_LOCAL = None
|
||||
@@ -45,13 +46,19 @@ class nosqlMySQL():
|
||||
def conn(self):
|
||||
|
||||
if self.__sid is None:
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
if self.__sid is not None:
|
||||
mycnf_path = "{}/{}/etc/my.cnf".format(mw.getServerDir(),self.__sid)
|
||||
if not os.path.exists(mycnf_path):
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
if not self.__config:
|
||||
self.__DB_STATUS = 'not_installed'
|
||||
return False
|
||||
|
||||
self.__DB_PORT = int(self.__config['port'])
|
||||
self.__DB_USER = self.__config['username']
|
||||
self.__DB_PASS = self.__config['password']
|
||||
@@ -65,11 +72,19 @@ class nosqlMySQL():
|
||||
if self.__DB_SOCKET != '':
|
||||
db.setSocket(self.__DB_SOCKET)
|
||||
|
||||
# 实际连通性检查:服务未启动或账号错误时返回 False,调用方统一提示
|
||||
db.query('select 1')
|
||||
self.__DB_STATUS = None
|
||||
return db
|
||||
except Exception:
|
||||
self.__DB_ERR = mw.get_error_info()
|
||||
self.__DB_ERR = mw.getTracebackInfo()
|
||||
self.__DB_STATUS = 'not_running'
|
||||
return False
|
||||
|
||||
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
|
||||
def get_status(self):
|
||||
return self.__DB_STATUS
|
||||
|
||||
def sqliteDb(self, db_pos_name, dbname='databases'):
|
||||
mydb_path = mw.getServerDir() +'/'+db_pos_name
|
||||
name = 'mysql'
|
||||
@@ -84,7 +99,7 @@ class nosqlMySQL():
|
||||
result['host'] = '127.0.0.1'
|
||||
result['username'] = 'root'
|
||||
|
||||
if sid in ['mysql', 'mysql-apt', 'mysql-yum', 'mysql-community']:
|
||||
if sid in ['mysql', 'mysql-apt', 'mysql-yum', 'mysql-community','mariadb']:
|
||||
my_cnf_path = "{}/{}/etc/my.cnf".format(mw.getServerDir(),sid)
|
||||
if not os.path.exists(my_cnf_path):
|
||||
return False
|
||||
@@ -136,6 +151,10 @@ class nosqlMySQL():
|
||||
local_mysql_yum = "{}/mysql-community/etc/my.cnf".format(mw.getServerDir())
|
||||
if os.path.exists(local_mysql_yum):
|
||||
data.append({'name':'本地服务器[Tar]', 'val':'mysql-community'})
|
||||
|
||||
local_mysql_yum = "{}/mariadb/etc/my.cnf".format(mw.getServerDir())
|
||||
if os.path.exists(local_mysql_yum):
|
||||
data.append({'name':'本地服务器[mariadb]', 'val':'mariadb'})
|
||||
return mw.returnData(True, 'ok', data)
|
||||
|
||||
@singleton
|
||||
@@ -153,11 +172,20 @@ class nosqlMySQLCtr():
|
||||
instance.setSid(sid)
|
||||
return instance
|
||||
|
||||
def _connect(self, sid):
|
||||
obj = self.getInstanceBySid(sid)
|
||||
conn = obj.conn()
|
||||
if conn is False:
|
||||
if obj.get_status() == 'not_installed':
|
||||
return None, mw.returnData(False, '未安装')
|
||||
return None, mw.returnData(False, '未启动')
|
||||
return conn, None
|
||||
|
||||
def getDbList(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = {}
|
||||
db_list = my_instance.query('show databases')
|
||||
@@ -172,9 +200,9 @@ class nosqlMySQLCtr():
|
||||
sid = args['sid']
|
||||
db = args['db']
|
||||
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
sql = "select * from information_schema.tables where table_schema = '"+db+"'"
|
||||
table_list = my_instance.query(sql)
|
||||
@@ -226,9 +254,9 @@ class nosqlMySQLCtr():
|
||||
else:
|
||||
where_sql = ' where '+args_where['field'] + " like '%"+args_where['value']+"%' "
|
||||
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
my_instance.setDbName(db)
|
||||
sql = 'select count(*) as num from ' + table + where_sql
|
||||
@@ -268,9 +296,9 @@ class nosqlMySQLCtr():
|
||||
sql = 'show processlist';
|
||||
sid = args['sid']
|
||||
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = my_instance.query(sql)
|
||||
rdata = {}
|
||||
@@ -281,9 +309,9 @@ class nosqlMySQLCtr():
|
||||
sql = 'show status';
|
||||
sid = args['sid']
|
||||
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = my_instance.query(sql)
|
||||
rdata = {}
|
||||
@@ -294,9 +322,9 @@ class nosqlMySQLCtr():
|
||||
sql = "show status like 'Com_%'";
|
||||
sid = args['sid']
|
||||
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
result = my_instance.query(sql)
|
||||
rdata = {}
|
||||
@@ -331,9 +359,9 @@ class nosqlMySQLCtr():
|
||||
def getNetList(self, args):
|
||||
from datetime import datetime
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
rdata = []
|
||||
row = {}
|
||||
@@ -369,9 +397,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def getTopnList(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
is_performance_schema = my_instance.find("SELECT @@performance_schema")
|
||||
if is_performance_schema is None:
|
||||
@@ -399,9 +427,9 @@ class nosqlMySQLCtr():
|
||||
# 查看重复或冗余的索引
|
||||
def getRedundantIndexes(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
is_performance_schema = my_instance.find("SELECT @@performance_schema")
|
||||
if is_performance_schema["@@performance_schema"] == 0:
|
||||
@@ -417,9 +445,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def redundantIndexesCmd(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
is_performance_schema = my_instance.find("SELECT @@performance_schema")
|
||||
if is_performance_schema["@@performance_schema"] == 0:
|
||||
@@ -442,29 +470,53 @@ class nosqlMySQLCtr():
|
||||
from decimal import Decimal
|
||||
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
my_instance.execute("SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''))")
|
||||
|
||||
# ANY_VALUE 是 MySQL 5.7+ 的函数,MariaDB 不支持(报 FUNCTION ANY_VALUE does not exist);
|
||||
# 上面已去掉 ONLY_FULL_GROUP_BY,MariaDB 可直接取非聚合字段
|
||||
ver = my_instance.find("SELECT @@version as db_version")
|
||||
is_mariadb = ver is not None and 'MariaDB' in str(ver.get('db_version', ''))
|
||||
|
||||
def any_val(expr):
|
||||
return expr if is_mariadb else 'ANY_VALUE(' + expr + ')'
|
||||
|
||||
data = my_instance.query(
|
||||
"""
|
||||
SELECT t.TABLE_SCHEMA as TABLE_SCHEMA, t.TABLE_NAME as TABLE_NAME, t.ENGINE as ENGINE,
|
||||
IFNULL(t.DATA_LENGTH/1024/1024/1024, 0) as DATA_LENGTH,
|
||||
IFNULL(t.INDEX_LENGTH/1024/1024/1024, 0) as INDEX_LENGTH,
|
||||
IFNULL((DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024, 0) AS TOTAL_LENGTH,
|
||||
c.column_name AS COLUMN_NAME, c.data_type AS DATA_TYPE, c.COLUMN_TYPE AS COLUMN_TYPE,
|
||||
t.AUTO_INCREMENT AS AUTO_INCREMENT, locate('unsigned', c.COLUMN_TYPE) = 0 AS IS_SIGNED
|
||||
FROM information_schema.TABLES t
|
||||
JOIN information_schema.COLUMNS c ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.table_name=c.table_name
|
||||
WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY TOTAL_LENGTH DESC, AUTO_INCREMENT DESC;
|
||||
"""
|
||||
SELECT t.TABLE_SCHEMA as TABLE_SCHEMA, t.TABLE_NAME as TABLE_NAME,
|
||||
{engine} as ENGINE,
|
||||
{data_length} as DATA_LENGTH,
|
||||
{index_length} as INDEX_LENGTH,
|
||||
{total_length} AS TOTAL_LENGTH,
|
||||
{column_name} AS COLUMN_NAME, {data_type} AS DATA_TYPE,
|
||||
{column_type} AS COLUMN_TYPE,
|
||||
{auto_increment} AS AUTO_INCREMENT,
|
||||
{is_signed} AS IS_SIGNED
|
||||
FROM information_schema.TABLES t
|
||||
JOIN information_schema.COLUMNS c ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.table_name=c.table_name
|
||||
WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
|
||||
GROUP BY t.TABLE_SCHEMA, t.TABLE_NAME
|
||||
ORDER BY TOTAL_LENGTH DESC, AUTO_INCREMENT DESC
|
||||
""".format(
|
||||
engine=any_val("t.ENGINE"),
|
||||
data_length=any_val("IFNULL(t.DATA_LENGTH/1024/1024/1024, 0)"),
|
||||
index_length=any_val("IFNULL(t.INDEX_LENGTH/1024/1024/1024, 0)"),
|
||||
total_length=any_val("IFNULL((t.DATA_LENGTH+t.INDEX_LENGTH)/1024/1024/1024, 0)"),
|
||||
column_name=any_val("c.column_name"),
|
||||
data_type=any_val("c.data_type"),
|
||||
column_type=any_val("c.COLUMN_TYPE"),
|
||||
auto_increment=any_val("t.AUTO_INCREMENT"),
|
||||
is_signed=any_val("locate('unsigned', c.COLUMN_TYPE) = 0"),
|
||||
)
|
||||
)
|
||||
|
||||
if data is None:
|
||||
return mw.returnData(True, 'ok', [])
|
||||
if isinstance(data, Exception):
|
||||
return mw.returnData(False, '查询失败: ' + str(data))
|
||||
|
||||
for i in range(len(data)):
|
||||
row = data[i]
|
||||
@@ -515,9 +567,9 @@ class nosqlMySQLCtr():
|
||||
# 查看应用端IP连接数总和
|
||||
def getConnCount(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
data = my_instance.query(
|
||||
"SELECT user,db,substring_index(HOST,':',1) AS Client_IP,count(1) AS count FROM information_schema.PROCESSLIST "
|
||||
@@ -539,9 +591,9 @@ class nosqlMySQLCtr():
|
||||
# 快速找出没有主键的表
|
||||
def getFpkInfo(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
data = my_instance.query(
|
||||
"""
|
||||
@@ -561,9 +613,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def getLockSql(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
data = my_instance.query(
|
||||
"""
|
||||
@@ -592,9 +644,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def killLockPid(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
pid = args['pid']
|
||||
my_instance.execute('kill %s' % pid)
|
||||
@@ -602,9 +654,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def killAllLock(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
data = self.getLockSql(args)
|
||||
if data['status']:
|
||||
@@ -619,9 +671,9 @@ class nosqlMySQLCtr():
|
||||
|
||||
def getDeadlockInfo(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
data = my_instance.find("SHOW ENGINE INNODB STATUS")
|
||||
if data is not None:
|
||||
@@ -634,29 +686,45 @@ class nosqlMySQLCtr():
|
||||
|
||||
def getSlaveStatus(self, args):
|
||||
sid = args['sid']
|
||||
my_instance = self.getInstanceBySid(sid).conn()
|
||||
if my_instance is False:
|
||||
return mw.returnData(False,'无法链接')
|
||||
my_instance, err = self._connect(sid)
|
||||
if err:
|
||||
return err
|
||||
|
||||
slave_info = my_instance.find('SHOW SLAVE STATUS')
|
||||
if slave_info is None:
|
||||
# MySQL 8.0.22+ 使用 SHOW REPLICA STATUS,MySQL 9.0 已移除 SHOW SLAVE STATUS
|
||||
slave_data = my_instance.query('SHOW REPLICA STATUS')
|
||||
if isinstance(slave_data, Exception):
|
||||
# 兼容 MySQL 8.0.22 以下及旧版 MariaDB
|
||||
slave_data = my_instance.query('SHOW SLAVE STATUS')
|
||||
if isinstance(slave_data, Exception):
|
||||
return mw.returnData(False, '获取主从状态失败: ' + str(slave_data))
|
||||
if slave_data is None or len(slave_data) == 0:
|
||||
return mw.returnData(True, 'ok', '未开启从库!')
|
||||
|
||||
slave_info = slave_data[0]
|
||||
# 兼容新旧字段名: MySQL 8.0.22+ 将 Slave_*/Seconds_Behind_Master 重命名为 Replica_*/Seconds_Behind_Source
|
||||
io_running = slave_info.get('Replica_IO_Running', slave_info.get('Slave_IO_Running'))
|
||||
sql_running = slave_info.get('Replica_SQL_Running', slave_info.get('Slave_SQL_Running'))
|
||||
seconds_behind = slave_info.get('Seconds_Behind_Source', slave_info.get('Seconds_Behind_Master'))
|
||||
|
||||
msg = ''
|
||||
if slave_info['Auto_Position'] != 1:
|
||||
if slave_info.get('Auto_Position') != 1:
|
||||
msg += '你没有开启基于GTID全局事务ID复制,请确保CHANGE MASTER TO MASTER_AUTO_POSITION = 1.\n'
|
||||
|
||||
|
||||
if slave_info['Slave_IO_Running'] == 'Yes' and slave_info['Slave_SQL_Running'] == 'Yes':
|
||||
if slave_info['Seconds_Behind_Master'] == 0:
|
||||
if io_running == 'Yes' and sql_running == 'Yes':
|
||||
if seconds_behind == 0:
|
||||
msg = "同步正常,无延迟"
|
||||
return mw.returnData(True, 'ok', msg)
|
||||
else:
|
||||
return mw.returnData(True, 'ok', '同步正常,但有延迟,延迟时间为:%s' % slave_info['Seconds_Behind_Master'])
|
||||
return mw.returnData(True, 'ok', '同步正常,但有延迟,延迟时间为:%s' % seconds_behind)
|
||||
else:
|
||||
msg = '主从复制报错,请检查\nSlave_IO_Running状态值是:%s, | Slave_SQL_Running状态值是:%s\nLast_Error错误信息是:%s\nLast_SQL_Error错误信息是:%s\n' \
|
||||
% (slave_info['Slave_IO_Running'], slave_info['Slave_SQL_Running'], slave_info['Last_Error'], slave_info['Last_SQL_Error'])
|
||||
error_dict = my_instance.find('select LAST_ERROR_NUMBER,LAST_ERROR_MESSAGE,LAST_ERROR_TIMESTAMP from performance_schema.replication_applier_status_by_worker ORDER BY LAST_ERROR_TIMESTAMP desc limit 1')
|
||||
% (io_running, sql_running, slave_info.get('Last_Error'), slave_info.get('Last_SQL_Error'))
|
||||
error_data = my_instance.query('select LAST_ERROR_NUMBER,LAST_ERROR_MESSAGE,LAST_ERROR_TIMESTAMP from performance_schema.replication_applier_status_by_worker ORDER BY LAST_ERROR_TIMESTAMP desc limit 1')
|
||||
if isinstance(error_data, Exception) or not error_data:
|
||||
msg += 'MySQL Replication Health is NOT OK!'
|
||||
return mw.returnData(True, 'ok', msg)
|
||||
error_dict = error_data[0]
|
||||
msg += '错误号是:%s \n' % error_dict['LAST_ERROR_NUMBER']
|
||||
msg += '错误信息是:%s \n' % error_dict['LAST_ERROR_MESSAGE']
|
||||
msg += '报错时间是:%s \n' % error_dict['LAST_ERROR_TIMESTAMP']
|
||||
|
||||
825
plugins/data_query/sql_postgresql.py
Executable file
825
plugins/data_query/sql_postgresql.py
Executable file
@@ -0,0 +1,825 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import time
|
||||
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
|
||||
web_dir = os.getcwd() + "/web"
|
||||
if os.path.exists(web_dir):
|
||||
sys.path.append(web_dir)
|
||||
os.chdir(web_dir)
|
||||
|
||||
import core.mw as mw
|
||||
|
||||
PG_SYSTEM_SCHEMAS = ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'postgresql'
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return mw.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getConf():
|
||||
return getServerDir() + '/data/postgresql.conf'
|
||||
|
||||
|
||||
def isInstalled():
|
||||
return os.path.exists(getConf())
|
||||
|
||||
|
||||
def getPort():
|
||||
content = mw.readFile(getConf())
|
||||
if content:
|
||||
tmp = re.search(r'^[#\s]*port\s*=\s*(\d+)', content, re.M)
|
||||
if tmp:
|
||||
return int(tmp.groups()[0])
|
||||
return 5432
|
||||
|
||||
|
||||
def getSocketDir():
|
||||
sock_name = '.s.PGSQL.' + str(getPort())
|
||||
for sock_dir in ['/tmp', getServerDir()]:
|
||||
if os.path.exists(sock_dir + '/' + sock_name):
|
||||
return sock_dir
|
||||
return ''
|
||||
|
||||
|
||||
def quoteIdent(name):
|
||||
return '"' + str(name).replace('"', '""') + '"'
|
||||
|
||||
|
||||
def quoteTable(name):
|
||||
return '.'.join(quoteIdent(x) for x in str(name).split('.'))
|
||||
|
||||
|
||||
def fmtValue(value):
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, (dict, list, tuple)):
|
||||
return json.dumps(value, ensure_ascii=False, default=str)
|
||||
if isinstance(value, (bytes, bytearray, memoryview)):
|
||||
return bytes(value).hex()
|
||||
if isinstance(value, (int, float, str, bool)):
|
||||
return value
|
||||
return str(value)
|
||||
|
||||
|
||||
def fmtRows(rows):
|
||||
ret = []
|
||||
for row in rows:
|
||||
item = {}
|
||||
for k in row:
|
||||
item[k] = fmtValue(row[k])
|
||||
ret.append(item)
|
||||
return ret
|
||||
|
||||
|
||||
class PgClient:
|
||||
|
||||
def __init__(self, database='postgres'):
|
||||
self.database = database
|
||||
self.status = None
|
||||
self.error = None
|
||||
self.conn = None
|
||||
|
||||
def connect(self):
|
||||
if not isInstalled():
|
||||
self.status = 'not_installed'
|
||||
return False
|
||||
|
||||
try:
|
||||
host = getSocketDir()
|
||||
if host == '':
|
||||
host = '127.0.0.1'
|
||||
|
||||
self.conn = psycopg2.connect(database=self.database,
|
||||
user='postgres',
|
||||
host=host,
|
||||
port=getPort(),
|
||||
connect_timeout=3)
|
||||
self.conn.autocommit = True
|
||||
return True
|
||||
except psycopg2.OperationalError as e:
|
||||
msg = str(e).strip()
|
||||
if 'does not exist' in msg:
|
||||
self.status = 'db_not_found'
|
||||
elif 'authentication' in msg or 'password' in msg:
|
||||
self.status = 'auth_error'
|
||||
else:
|
||||
self.status = 'not_running'
|
||||
self.error = msg
|
||||
except Exception as e:
|
||||
self.status = 'not_running'
|
||||
self.error = str(e)
|
||||
return False
|
||||
|
||||
def query(self, sql, params=()):
|
||||
cur = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||
try:
|
||||
# 无参数时不能传空 tuple,否则 SQL 里的 % 会被当作占位符
|
||||
if params:
|
||||
cur.execute(sql, params)
|
||||
else:
|
||||
cur.execute(sql)
|
||||
rows = cur.fetchall()
|
||||
return [dict(x) for x in rows]
|
||||
finally:
|
||||
cur.close()
|
||||
|
||||
def one(self, sql, params=()):
|
||||
rows = self.query(sql, params)
|
||||
if len(rows) == 0:
|
||||
return None
|
||||
return rows[0]
|
||||
|
||||
def execute(self, sql, params=()):
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
if params:
|
||||
cur.execute(sql, params)
|
||||
else:
|
||||
cur.execute(sql)
|
||||
return cur.rowcount
|
||||
finally:
|
||||
cur.close()
|
||||
|
||||
def close(self):
|
||||
if self.conn:
|
||||
self.conn.close()
|
||||
self.conn = None
|
||||
|
||||
|
||||
def openClient(args, database='postgres'):
|
||||
client = PgClient(database)
|
||||
if client.connect():
|
||||
return client, None
|
||||
|
||||
if client.status == 'not_installed':
|
||||
msg = '未安装'
|
||||
elif client.status == 'not_running':
|
||||
msg = '未启动'
|
||||
elif client.status == 'db_not_found':
|
||||
msg = '数据库不存在'
|
||||
elif client.status == 'auth_error':
|
||||
msg = '连接失败,请检查数据库认证配置'
|
||||
else:
|
||||
msg = client.error or '连接失败'
|
||||
return None, mw.returnData(False, msg)
|
||||
|
||||
|
||||
# 服务器列表
|
||||
def get_server_list(args):
|
||||
data = []
|
||||
if isInstalled():
|
||||
data.append({'name': '本地服务器', 'val': 'postgresql'})
|
||||
return mw.returnData(True, 'ok', data)
|
||||
|
||||
|
||||
# 数据库列表
|
||||
def get_db_list(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
rows = client.query("select datname from pg_database where datistemplate = false order by datname")
|
||||
result = {'list': [x['datname'] for x in rows]}
|
||||
return mw.returnData(True, 'ok', result)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 数据表列表
|
||||
def get_table_list(args):
|
||||
db = args.get('db', '')
|
||||
client, err = openClient(args, db)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select n.nspname as schemaname, c.relname as tablename
|
||||
from pg_class c
|
||||
join pg_namespace n on n.oid = c.relnamespace
|
||||
where c.relkind in ('r', 'p', 'v', 'm', 'f')
|
||||
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
and n.nspname not like 'pg_temp%'
|
||||
order by n.nspname, c.relname
|
||||
"""
|
||||
rows = client.query(sql)
|
||||
|
||||
table_list = []
|
||||
for x in rows:
|
||||
if x['schemaname'] == 'public':
|
||||
table_list.append(x['tablename'])
|
||||
else:
|
||||
table_list.append(x['schemaname'] + '.' + x['tablename'])
|
||||
|
||||
result = {'list': table_list}
|
||||
return mw.returnData(True, 'ok', result)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 数据列表
|
||||
def get_data_list(args):
|
||||
db = args.get('db', '')
|
||||
table = args.get('table', '')
|
||||
|
||||
p = 1
|
||||
size = 10
|
||||
if 'p' in args:
|
||||
p = int(args['p'])
|
||||
if 'size' in args:
|
||||
size = int(args['size'])
|
||||
start_index = (p - 1) * size
|
||||
|
||||
if table == '':
|
||||
page_args = {}
|
||||
page_args['count'] = 0
|
||||
page_args['tojs'] = 'pgGetDataList'
|
||||
page_args['p'] = 1
|
||||
page_args['row'] = size
|
||||
|
||||
rdata = {}
|
||||
rdata['page'] = mw.getPage(page_args)
|
||||
rdata['list'] = []
|
||||
rdata['count'] = 0
|
||||
return mw.returnData(True, 'ok', rdata)
|
||||
|
||||
where_sql = ''
|
||||
where_params = []
|
||||
args_where = {}
|
||||
if 'where' in args and isinstance(args['where'], dict):
|
||||
args_where = args['where']
|
||||
|
||||
field = args_where.get('field', '')
|
||||
if field and field != '0':
|
||||
field_sql = quoteIdent(field)
|
||||
value = str(args_where.get('value', ''))
|
||||
if 'id' in field.lower():
|
||||
where_sql = ' where ' + field_sql + ' = %s'
|
||||
where_params.append(value)
|
||||
else:
|
||||
where_sql = ' where ' + field_sql + ' like %s'
|
||||
where_params.append('%' + value + '%')
|
||||
|
||||
client, err = openClient(args, db)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
try:
|
||||
sql = 'select count(*) as num from ' + quoteTable(table) + where_sql
|
||||
count_row = client.one(sql, tuple(where_params))
|
||||
count = int(count_row['num'])
|
||||
|
||||
sql = 'select * from ' + quoteTable(table) + where_sql + ' limit %s offset %s'
|
||||
params = tuple(where_params) + (size, start_index)
|
||||
rows = client.query(sql, params)
|
||||
rows = fmtRows(rows)
|
||||
except psycopg2.errors.UndefinedTable:
|
||||
return mw.returnData(False, '数据表不存在:' + table)
|
||||
except psycopg2.errors.UndefinedColumn:
|
||||
return mw.returnData(False, '字段不存在,请刷新后重试')
|
||||
except psycopg2.Error as e:
|
||||
return mw.returnData(False, '查询失败:' + str(e).strip())
|
||||
|
||||
page_args = {}
|
||||
page_args['count'] = count
|
||||
page_args['tojs'] = 'pgGetDataList'
|
||||
page_args['p'] = p
|
||||
page_args['row'] = size
|
||||
|
||||
rdata = {}
|
||||
rdata['page'] = mw.getPage(page_args)
|
||||
rdata['list'] = rows
|
||||
rdata['count'] = count
|
||||
rdata['soso_field'] = ''
|
||||
if field and field != '0':
|
||||
rdata['soso_field'] = field
|
||||
|
||||
return mw.returnData(True, 'ok', rdata)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 进程列表
|
||||
def get_proccess_list(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select pid, usename as "user", datname as db,
|
||||
coalesce(host(client_addr), '本地') as host,
|
||||
application_name as command, state, query as info,
|
||||
backend_start, xact_start, query_start,
|
||||
wait_event_type, wait_event
|
||||
from pg_stat_activity
|
||||
where pid <> pg_backend_pid()
|
||||
and backend_type = 'client backend'
|
||||
order by pid
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
result = {'list': rows}
|
||||
return mw.returnData(True, 'ok', result)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 状态列表
|
||||
def get_status_list(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select name, setting, coalesce(unit, '') as unit,
|
||||
category, short_desc
|
||||
from pg_settings
|
||||
order by name
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
result = {'list': rows}
|
||||
return mw.returnData(True, 'ok', result)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 统计列表
|
||||
def get_stats_list(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select datname as db,
|
||||
numbackends as conn,
|
||||
xact_commit as commit, xact_rollback as rollback,
|
||||
blks_read, blks_hit,
|
||||
tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted,
|
||||
deadlocks, conflicts, temp_files, temp_bytes,
|
||||
round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) as cache_hit_ratio
|
||||
from pg_stat_database
|
||||
where datname is not null
|
||||
order by datname
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
result = {'list': rows}
|
||||
return mw.returnData(True, 'ok', result)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
def _dbStatSnapshot(client):
|
||||
sql = """
|
||||
select coalesce(sum(tup_fetched), 0) as fetched,
|
||||
coalesce(sum(tup_inserted), 0) as inserted,
|
||||
coalesce(sum(tup_updated), 0) as updated,
|
||||
coalesce(sum(tup_deleted), 0) as deleted,
|
||||
coalesce(sum(xact_commit), 0) as commits
|
||||
from pg_stat_database
|
||||
"""
|
||||
row = client.one(sql)
|
||||
return {
|
||||
'fetched': int(row['fetched']),
|
||||
'inserted': int(row['inserted']),
|
||||
'updated': int(row['updated']),
|
||||
'deleted': int(row['deleted']),
|
||||
'commits': int(row['commits']),
|
||||
}
|
||||
|
||||
|
||||
# QPS/TPS 指标
|
||||
def get_net_list(args):
|
||||
from datetime import datetime
|
||||
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
row1 = _dbStatSnapshot(client)
|
||||
time.sleep(1)
|
||||
row2 = _dbStatSnapshot(client)
|
||||
|
||||
max_conn = client.one("select setting from pg_settings where name = 'max_connections'")
|
||||
conn_row = client.one("select count(*) as num from pg_stat_activity where backend_type = 'client backend'")
|
||||
|
||||
row = {}
|
||||
row['current_time'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
row['select'] = row2['fetched'] - row1['fetched']
|
||||
row['insert'] = row2['inserted'] - row1['inserted']
|
||||
row['update'] = row2['updated'] - row1['updated']
|
||||
row['delete'] = row2['deleted'] - row1['deleted']
|
||||
row['conn'] = conn_row['num']
|
||||
row['max_conn'] = max_conn['setting']
|
||||
# PostgreSQL 的 pg_stat 不提供网络字节计数器
|
||||
row['recv_mbps'] = '-'
|
||||
row['send_mbps'] = '-'
|
||||
|
||||
rdata = []
|
||||
rdata.append(row)
|
||||
return mw.returnData(True, 'ok', rdata)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 查询执行次数最频繁的前N条SQL语句
|
||||
def get_topn_list(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
avail = client.one("""
|
||||
select default_version, installed_version
|
||||
from pg_available_extensions
|
||||
where name = 'pg_stat_statements'
|
||||
""")
|
||||
if avail is None:
|
||||
return mw.returnData(False, '当前 PostgreSQL 未提供 pg_stat_statements 扩展(缺少 contrib 模块),无法使用该功能。')
|
||||
|
||||
# 先检查 shared_preload_libraries —— pg_stat_statements 必须预加载
|
||||
preload = client.one("select setting from pg_settings where name = 'shared_preload_libraries'")
|
||||
libs = (preload or {}).get('setting', '') or ''
|
||||
if 'pg_stat_statements' not in libs:
|
||||
return mw.returnData(False, "pg_stat_statements 扩展必须在启动时预加载。\n"
|
||||
"请在 postgresql.conf 添加 shared_preload_libraries = 'pg_stat_statements' 后重启 PostgreSQL。")
|
||||
|
||||
# 再检查扩展是否已 CREATE
|
||||
ext = client.one("select to_regclass('pg_stat_statements') as v")
|
||||
if ext is None or ext['v'] is None:
|
||||
return mw.returnData(False, "pg_stat_statements 扩展已预加载,但尚未启用。\n"
|
||||
"请在当前数据库执行 CREATE EXTENSION pg_stat_statements;")
|
||||
|
||||
version_num = int(client.one('show server_version_num')['server_version_num'])
|
||||
if version_num >= 130000:
|
||||
total_col = 'total_exec_time'
|
||||
max_col = 'max_exec_time'
|
||||
mean_col = 'mean_exec_time'
|
||||
else:
|
||||
total_col = 'total_time'
|
||||
max_col = 'max_time'
|
||||
mean_col = 'mean_time'
|
||||
|
||||
sql = """
|
||||
select s.query,
|
||||
coalesce(d.datname, '-') as db,
|
||||
'-' as last_seen,
|
||||
s.calls as exec_count,
|
||||
round(s.{max_col}::numeric, 2) as max_latency,
|
||||
round(s.{mean_col}::numeric, 2) as avg_latency
|
||||
from pg_stat_statements s
|
||||
left join pg_database d on d.oid = s.dbid
|
||||
""".format(max_col=max_col, mean_col=mean_col)
|
||||
|
||||
filter_db = args.get('filter_db', 'no')
|
||||
if filter_db == 'yes':
|
||||
sql += ' where d.datname is not null '
|
||||
|
||||
sql += ' order by s.calls desc limit 20'
|
||||
rows = fmtRows(client.query(sql))
|
||||
return mw.returnData(True, 'ok', rows)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
def _redundantIndexes(client):
|
||||
sql = """
|
||||
select n.nspname as table_schema,
|
||||
t.relname as table_name,
|
||||
ic.relname as redundant_index_name,
|
||||
coalesce((
|
||||
select string_agg(a.attname, ',' order by k.ord)
|
||||
from unnest(i.indkey) with ordinality as k(attnum, ord)
|
||||
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
|
||||
), '') as redundant_index_columns,
|
||||
'DROP INDEX ' || quote_ident(n.nspname) || '.' || quote_ident(ic.relname) as sql_drop_index
|
||||
from pg_index i
|
||||
join pg_class t on t.oid = i.indrelid
|
||||
join pg_namespace n on n.oid = t.relnamespace
|
||||
join pg_class ic on ic.oid = i.indexrelid
|
||||
where n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
and not exists (
|
||||
select 1 from pg_constraint con where con.conindid = i.indexrelid
|
||||
)
|
||||
and exists (
|
||||
select 1
|
||||
from pg_index i2
|
||||
join pg_class ic2 on ic2.oid = i2.indexrelid
|
||||
where i2.indrelid = i.indrelid
|
||||
and i2.indkey = i.indkey
|
||||
and i2.indclass = i.indclass
|
||||
and i2.indcollation = i.indcollation
|
||||
and i2.indpred is not distinct from i.indpred
|
||||
and i2.indexprs is not distinct from i.indexprs
|
||||
and i2.indexrelid <> i.indexrelid
|
||||
and ic2.relname < ic.relname
|
||||
)
|
||||
order by 1, 2, 3
|
||||
"""
|
||||
return fmtRows(client.query(sql))
|
||||
|
||||
|
||||
# 查看重复或冗余的索引
|
||||
def get_redundant_indexes(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
rows = _redundantIndexes(client)
|
||||
return mw.returnData(True, 'ok', rows)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 删除重复或冗余的索引
|
||||
def redundant_indexes_cmd(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
rows = _redundantIndexes(client)
|
||||
index = int(args['index'])
|
||||
if index >= len(rows):
|
||||
return mw.returnData(False, '索引不存在,请刷新后重试')
|
||||
|
||||
client.execute(rows[index]['sql_drop_index'])
|
||||
return mw.returnData(True, '执行成功!')
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 统计库里每个表的大小
|
||||
def get_table_info(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select n.nspname as "TABLE_SCHEMA",
|
||||
c.relname as "TABLE_NAME",
|
||||
case c.relkind
|
||||
when 'r' then 'table'
|
||||
when 'p' then 'partitioned table'
|
||||
when 'v' then 'view'
|
||||
when 'm' then 'materialized view'
|
||||
else c.relkind::text
|
||||
end as "ENGINE",
|
||||
c.reltuples as rows_estimate,
|
||||
pg_relation_size(c.oid) as data_bytes,
|
||||
pg_indexes_size(c.oid) as index_bytes,
|
||||
pg_total_relation_size(c.oid) as total_bytes,
|
||||
coalesce((
|
||||
select string_agg(a.attname, ',' order by k.ord)
|
||||
from pg_index i
|
||||
join unnest(i.indkey) with ordinality as k(attnum, ord) on true
|
||||
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
|
||||
where i.indrelid = c.oid and i.indisprimary
|
||||
), '-') as "COLUMN_NAME",
|
||||
coalesce((
|
||||
select string_agg(format_type(a.atttypid, a.atttypmod), ',' order by k.ord)
|
||||
from pg_index i
|
||||
join unnest(i.indkey) with ordinality as k(attnum, ord) on true
|
||||
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
|
||||
where i.indrelid = c.oid and i.indisprimary
|
||||
), '-') as "COLUMN_TYPE"
|
||||
from pg_class c
|
||||
join pg_namespace n on n.oid = c.relnamespace
|
||||
where c.relkind in ('r', 'p', 'v', 'm')
|
||||
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
and n.nspname not like 'pg_temp%'
|
||||
order by total_bytes desc
|
||||
"""
|
||||
rows = client.query(sql)
|
||||
|
||||
for i in range(len(rows)):
|
||||
row = rows[i]
|
||||
row['DATA_LENGTH'] = round(float(row['data_bytes'] or 0) / 1024 / 1024 / 1024, 2)
|
||||
row['INDEX_LENGTH'] = round(float(row['index_bytes'] or 0) / 1024 / 1024 / 1024, 2)
|
||||
row['TOTAL_LENGTH'] = round(float(row['total_bytes'] or 0) / 1024 / 1024 / 1024, 2)
|
||||
# PostgreSQL 没有 AUTO_INCREMENT,使用 SEQUENCE / IDENTITY
|
||||
row['AUTO_INCREMENT'] = '-'
|
||||
row['RESIDUAL_AUTO_INCREMENT'] = '使用 SEQUENCE/IDENTITY'
|
||||
row['ROWS_ESTIMATE'] = int(row['rows_estimate'] or 0)
|
||||
del row['data_bytes']
|
||||
del row['index_bytes']
|
||||
del row['total_bytes']
|
||||
|
||||
return mw.returnData(True, 'ok', fmtRows(rows))
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 查看应用端IP连接数总和
|
||||
def get_conn_count(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select usename as "user",
|
||||
coalesce(datname, '空') as db,
|
||||
coalesce(host(client_addr), '本地') as "Client_IP",
|
||||
count(*) as count
|
||||
from pg_stat_activity
|
||||
where backend_type = 'client backend'
|
||||
group by usename, datname, client_addr
|
||||
order by count desc
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
return mw.returnData(True, 'ok', rows)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 快速找出没有主键的表
|
||||
def get_fpk_info(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select n.nspname as table_schema, c.relname as table_name
|
||||
from pg_class c
|
||||
join pg_namespace n on n.oid = c.relnamespace
|
||||
where c.relkind in ('r', 'p')
|
||||
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
and not exists (
|
||||
select 1 from pg_index i
|
||||
where i.indrelid = c.oid and i.indisprimary
|
||||
)
|
||||
order by n.nspname, c.relname
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
return mw.returnData(True, 'ok', rows)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 查看当前锁阻塞的SQL
|
||||
def get_lock_sql(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select coalesce(a.backend_xid::text, '-') as trx_id,
|
||||
'等待锁' as trx_state,
|
||||
a.xact_start as trx_started,
|
||||
a.pid as processlist_id,
|
||||
a.query as info,
|
||||
a.usename as "user",
|
||||
coalesce(host(a.client_addr), '本地') as host,
|
||||
a.datname as db,
|
||||
coalesce(a.wait_event_type, '-') as command,
|
||||
a.state,
|
||||
'SELECT pg_cancel_backend(' || a.pid || ')' as sql_kill_blocking_query,
|
||||
pg_blocking_pids(a.pid) as blocking_pids
|
||||
from pg_stat_activity a
|
||||
where cardinality(pg_blocking_pids(a.pid)) > 0
|
||||
and a.backend_type = 'client backend'
|
||||
order by a.xact_start
|
||||
"""
|
||||
rows = fmtRows(client.query(sql))
|
||||
return mw.returnData(True, 'ok', rows)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 终止阻塞会话
|
||||
def kill_lock_pid(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
pid = int(args['pid'])
|
||||
data = client.one('select pg_terminate_backend(%s) as ok', (pid,))
|
||||
if data is None or data['ok'] is not True:
|
||||
return mw.returnData(False, '结束会话失败,请检查会话是否存在')
|
||||
return mw.returnData(True, '执行成功!')
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 终止所有阻塞会话
|
||||
def kill_all_lock(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
sql = """
|
||||
select distinct unnest(pg_blocking_pids(pid)) as pid
|
||||
from pg_stat_activity
|
||||
where cardinality(pg_blocking_pids(pid)) > 0
|
||||
and backend_type = 'client backend'
|
||||
"""
|
||||
rows = client.query(sql)
|
||||
count = 0
|
||||
for x in rows:
|
||||
data = client.one('select pg_terminate_backend(%s) as ok', (x['pid'],))
|
||||
if data is not None and data['ok'] is True:
|
||||
count += 1
|
||||
return mw.returnData(True, '执行成功,已结束 %s 个阻塞会话' % count)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 查看死锁信息
|
||||
def get_deadlock_info(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
deadlocks = client.one('select coalesce(sum(deadlocks), 0) as num from pg_stat_database')
|
||||
locks = client.query("""
|
||||
select pid, usename as "user", datname as db, state,
|
||||
coalesce(wait_event_type, '-') as wait_event_type,
|
||||
query
|
||||
from pg_stat_activity
|
||||
where cardinality(pg_blocking_pids(pid)) > 0
|
||||
and backend_type = 'client backend'
|
||||
""")
|
||||
|
||||
msg = 'PostgreSQL 不保存历史死锁明细,仅提供累计次数与当前锁等待。\n'
|
||||
msg += '数据库累计死锁次数:%s\n' % deadlocks['num']
|
||||
if len(locks) == 0:
|
||||
msg += '当前没有处于锁等待的会话。'
|
||||
else:
|
||||
msg += '当前锁等待会话:\n'
|
||||
for x in locks:
|
||||
msg += 'pid=%s user=%s db=%s state=%s wait=%s\nquery=%s\n' % (
|
||||
x['pid'], x['user'], x['db'], x['state'], x['wait_event_type'], x['query'])
|
||||
return mw.returnData(True, 'ok', msg)
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
# 查看主从复制信息
|
||||
def get_slave_status(args):
|
||||
client, err = openClient(args)
|
||||
if err:
|
||||
return err
|
||||
|
||||
try:
|
||||
recovery = client.one('select pg_is_in_recovery() as recovery')['recovery']
|
||||
|
||||
if recovery is False:
|
||||
reps = client.query("""
|
||||
select client_addr, application_name, state, sync_state,
|
||||
sent_lsn, write_lsn, flush_lsn, replay_lsn,
|
||||
coalesce(replay_lag::text, '-') as replay_lag
|
||||
from pg_stat_replication
|
||||
""")
|
||||
if len(reps) == 0:
|
||||
return mw.returnData(True, 'ok', '未开启主从复制:当前为主库,且没有复制的从库连接。')
|
||||
|
||||
msg = '当前为主库,从库复制状态:\n'
|
||||
for x in reps:
|
||||
msg += '从库地址:%s 应用:%s\n' % (x['client_addr'], x['application_name'])
|
||||
msg += '状态:%s 同步模式:%s\n' % (x['state'], x['sync_state'])
|
||||
msg += 'sent_lsn=%s write_lsn=%s flush_lsn=%s replay_lsn=%s\n' % (
|
||||
x['sent_lsn'], x['write_lsn'], x['flush_lsn'], x['replay_lsn'])
|
||||
msg += 'replay_lag=%s\n\n' % x['replay_lag']
|
||||
return mw.returnData(True, 'ok', msg)
|
||||
|
||||
# 当前为从库
|
||||
lag = client.one("""
|
||||
select coalesce(extract(epoch from (now() - pg_last_xact_replay_timestamp()))::int, 0) as lag
|
||||
""")
|
||||
lsn = client.one("""
|
||||
select pg_last_wal_receive_lsn() as receive_lsn,
|
||||
pg_last_wal_replay_lsn() as replay_lsn,
|
||||
pg_last_xact_replay_timestamp() as replay_time
|
||||
""")
|
||||
|
||||
msg = '当前为从库,复制状态:\n'
|
||||
msg += 'receive_lsn=%s\n' % lsn['receive_lsn']
|
||||
msg += 'replay_lsn=%s\n' % lsn['replay_lsn']
|
||||
msg += '最近回放时间=%s\n' % lsn['replay_time']
|
||||
msg += '延迟时间:%s 秒' % lag['lag']
|
||||
return mw.returnData(True, 'ok', msg)
|
||||
finally:
|
||||
client.close()
|
||||
@@ -6,6 +6,7 @@
|
||||
<div class="tabs-item" data-name="mongodb">Mongodb</div>
|
||||
<div class="tabs-item" data-name="memcached">Memcached</div>
|
||||
<div class="tabs-item" data-name="mysql">MySQL</div>
|
||||
<div class="tabs-item" data-name="postgresql">PostgreSQL</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +17,99 @@
|
||||
<div class="prompt_description">当前未安装本地服务器,<a class="btlink install_server" href="/soft/index">点击安装</a></div>
|
||||
</div>
|
||||
|
||||
<!-- postgresql start -->
|
||||
<div class="tab-con hide" id="postgresql" style="padding: 0px;">
|
||||
|
||||
<div class="col-md-12" style="padding: 0px;overflow: hidden;">
|
||||
<div class="tootls_group tootls_top">
|
||||
<div class="pull-left">
|
||||
<div class="pgserver_list" style="float:left;">
|
||||
<select name="sid" class="bt-input-text c5 mr5">
|
||||
<option value="0">本地服务器</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="postgresql_db_list" style="float:left;">
|
||||
<select name="postgresql_db" class="bt-input-text c5 mr5">
|
||||
<option value="0">数据库空</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="postgresql_table_list" style="float:left;">
|
||||
<select name="postgresql_table" class="bt-input-text c5 mr5">
|
||||
<option value="0">数据表空</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="field" style="float:left;">
|
||||
<select name="postgresql_field_key" class="bt-input-text c5 mr5" style="width:80px;">
|
||||
<option value="0">无字段</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="value" style="float:left;">
|
||||
<input name="postgresql_field_value" type="text" class="bt-input-text" placeholder="请输入查找内容">
|
||||
</div>
|
||||
|
||||
|
||||
<div style="float:left;">
|
||||
<button id="postgresql_find" type="button" class="btn btn-success btn-sm mr5 ml5" >查找</button>
|
||||
<button id="postgresql_common" type="button" class="btn btn-success btn-sm mr5 ml5">常用功能</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="position: relative;">
|
||||
<div id="postgresql_table" class="postgresql_table divtable mtb10">
|
||||
<table class="table table-hover">
|
||||
<thead style="position: relative;z-index: 1;">
|
||||
<tr>
|
||||
<th><span>编号</span></th>
|
||||
<th><span>操作类型</span></th>
|
||||
<th><span>详情</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="postgresql_list_page page">
|
||||
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="border:none;" />
|
||||
|
||||
<div class="col-md-12" style="padding-left: 3px;">
|
||||
<div id="postgresql_list_tab" style="padding-top:0px;">
|
||||
<div class="tab-nav">
|
||||
<span data-name="proccess" class="on">进程</span>
|
||||
<span data-name="status" class="">状态</span>
|
||||
<span data-name="stats" class="">统计</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="position: relative;">
|
||||
<div id="postgresql_ot_table" class="divtable">
|
||||
<table class="table table-hover">
|
||||
<thead style="position: relative;z-index: 1;">
|
||||
<tr>
|
||||
<th><span>编号</span></th>
|
||||
<th><span>操作类型</span></th>
|
||||
<th><span>详情</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- postgresql end -->
|
||||
|
||||
<!-- mysql start -->
|
||||
<!-- show w-full -->
|
||||
<div class="tab-con hide" id="mysql" style="padding: 0px;">
|
||||
|
||||
@@ -143,6 +143,60 @@ function myPostCBN(method, args, callback){
|
||||
},'json');
|
||||
}
|
||||
|
||||
function pgPostCB(method, args, callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
|
||||
var req_data = {};
|
||||
req_data['name'] = 'data_query';
|
||||
req_data['func'] = method;
|
||||
req_data['script']='sql_postgresql';
|
||||
args['version'] = '';
|
||||
|
||||
if (typeof(args) == 'string' && args == ''){
|
||||
req_data['args'] = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
req_data['args'] = JSON.stringify(args);
|
||||
}
|
||||
|
||||
$.post('/plugins/callback', req_data, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function pgPostCBN(method, args, callback){
|
||||
var req_data = {};
|
||||
req_data['name'] = 'data_query';
|
||||
req_data['func'] = method;
|
||||
req_data['script']='sql_postgresql';
|
||||
args['version'] = '';
|
||||
|
||||
if (typeof(args) == 'string' && args == ''){
|
||||
req_data['args'] = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
req_data['args'] = JSON.stringify(args);
|
||||
}
|
||||
|
||||
$.post('/plugins/callback', req_data, function(data) {
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function selectTab(tab = 'redis'){
|
||||
$('.tab-view-box .tab-con').addClass('hide').removeClass('show').removeClass('w-full');
|
||||
@@ -163,6 +217,7 @@ function initTabFunc(tab){
|
||||
case 'mongodb':initTabMongodb();break;
|
||||
case 'memcached':initTabMemcached();break;
|
||||
case 'mysql':initTabMySQL();break;
|
||||
case 'postgresql':initTabPostgresql();break;
|
||||
case 'default:':initTabRedis();break;
|
||||
}
|
||||
}
|
||||
@@ -237,7 +292,7 @@ function initTabMemcached(){
|
||||
$('#memcached_clear_all').unbind('click').click(function(){
|
||||
var sid = memcachedGetSid();
|
||||
memPostCB('clear',{'sid':sid} ,function(rdata){
|
||||
// console.log(rdata);
|
||||
console.log("xxx",rdata);
|
||||
showMsg(rdata.data.msg,function(){
|
||||
if (rdata.data.status){
|
||||
memcachedGetList();
|
||||
@@ -927,6 +982,7 @@ function mysqlInitField(f, data){
|
||||
|
||||
|
||||
function mysqlGetServerList(call_func){
|
||||
closeInstallLayer();
|
||||
myPostCBN('get_server_list', {}, function(rdata){
|
||||
var rdata = rdata.data;
|
||||
if (rdata.data.length != 0){
|
||||
@@ -951,7 +1007,10 @@ function mysqlGetServerList(call_func){
|
||||
}
|
||||
closeInstallLayer();
|
||||
} else {
|
||||
showInstallLayer();
|
||||
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
|
||||
setTimeout(function(){
|
||||
showInstallLayer();
|
||||
},2050);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1201,9 +1260,9 @@ function memcachedGetItem(){
|
||||
|
||||
function memcachedGetList(){
|
||||
var sid = memcachedGetSid();
|
||||
closeInstallLayer();
|
||||
memPostCB('get_items',{'sid':sid} ,function(rdata){
|
||||
if (rdata.data.status){
|
||||
|
||||
var items = rdata.data.data['items'];
|
||||
var content = '';
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
@@ -1219,10 +1278,14 @@ function memcachedGetList(){
|
||||
memcachedGetKeyList(1);
|
||||
});
|
||||
closeInstallLayer();
|
||||
memcachedGetKeyList(1);
|
||||
} else {
|
||||
showInstallLayer();
|
||||
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
|
||||
setTimeout(function(){
|
||||
showInstallLayer();
|
||||
},2050);
|
||||
}
|
||||
memcachedGetKeyList(1);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1386,7 +1449,6 @@ function mongodbInitField(f, data){
|
||||
|
||||
var mogodb_db_list;
|
||||
function mongodbCollectionName(){
|
||||
// console.log(mogodb_db_list);
|
||||
var v = mogodb_db_list.getValue('value');
|
||||
if (v.length == 0){
|
||||
// console.log($('#mongodb').data('collection'));
|
||||
@@ -1397,6 +1459,7 @@ function mongodbCollectionName(){
|
||||
|
||||
function mongodbGetList(){
|
||||
var sid = mongodbGetSid();
|
||||
closeInstallLayer();
|
||||
mgdbPostCB('get_db_list',{'sid':sid} ,function(rdata){
|
||||
// console.log(rdata);
|
||||
if (rdata.data.status){
|
||||
@@ -1423,7 +1486,11 @@ function mongodbGetList(){
|
||||
|
||||
closeInstallLayer();
|
||||
} else {
|
||||
showInstallLayer();
|
||||
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
|
||||
setTimeout(function(){
|
||||
showInstallLayer();
|
||||
},2050);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1606,6 +1673,7 @@ function redisGetIdx(){
|
||||
|
||||
function redisGetList(){
|
||||
var sid = redisGetSid();
|
||||
closeInstallLayer();
|
||||
redisPostCB('get_list',{'sid':sid} ,function(rdata){
|
||||
if (rdata.data.status){
|
||||
var list = rdata.data.data;
|
||||
@@ -1627,7 +1695,10 @@ function redisGetList(){
|
||||
redisGetKeyList(1);
|
||||
closeInstallLayer();
|
||||
} else {
|
||||
showInstallLayer();
|
||||
layer.msg(rdata.data.msg,{ icon: 7, time: 1000, shade: 0.3 });
|
||||
setTimeout(function(){
|
||||
showInstallLayer();
|
||||
},1050);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1936,3 +2007,663 @@ function redisBatchClear(){
|
||||
}
|
||||
// ------------------------- redis end ---------------------------------
|
||||
|
||||
// ------------------------- postgresql start -------------------------------
|
||||
var pg_timer = null;
|
||||
var pg_last_error = '';
|
||||
|
||||
function pgToastError(msg){
|
||||
// 轮询失败时避免每 2 秒重复弹出相同的提示
|
||||
if (!msg || pg_last_error == msg){
|
||||
return;
|
||||
}
|
||||
pg_last_error = msg;
|
||||
layer.msg(msg,{icon:7,time:2500});
|
||||
}
|
||||
|
||||
function pgHtml(v){
|
||||
if (v === null || v === undefined){
|
||||
return '';
|
||||
}
|
||||
return String(v).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
|
||||
function pgGetSid(){
|
||||
return $('#postgresql select[name=sid]').val();
|
||||
}
|
||||
|
||||
function pgGetDbName(){
|
||||
return $('#postgresql .postgresql_db_list select[name=postgresql_db]').val();
|
||||
}
|
||||
|
||||
function pgGetTableName(){
|
||||
var table = $('#postgresql .postgresql_table_list select[name=postgresql_table]').val();
|
||||
if (!table || table == '0'){
|
||||
return '';
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
function pgShowNotice(title, msg){
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: ['560px', '260px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd20"><pre style="white-space:pre-wrap;word-break:break-all;margin:0;line-height:1.8;">'+pgHtml(msg)+'</pre></div>'
|
||||
});
|
||||
}
|
||||
|
||||
function pgModalTable(title, list, width, height){
|
||||
if (!list || list.length == 0){
|
||||
layer.msg('暂无数据',{icon:7});
|
||||
return;
|
||||
}
|
||||
|
||||
var fields = mongodbGetDataFields(list);
|
||||
var thead = '';
|
||||
for (var i = 0; i < fields.length; i++){
|
||||
thead += '<th>'+pgHtml(fields[i])+'</th>';
|
||||
}
|
||||
|
||||
var tbody = '';
|
||||
for (var i = 0; i < list.length; i++){
|
||||
tbody += '<tr>';
|
||||
for (var j = 0; j < fields.length; j++){
|
||||
var f = fields[j];
|
||||
var val = (f in list[i]) ? list[i][f] : '';
|
||||
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
|
||||
}
|
||||
tbody += '</tr>';
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: [width || '900px', height || '420px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd20 divtable taskdivtable" style="height:'+(parseInt(height || '420') - 80)+'px;overflow:auto;">\
|
||||
<table class="table table-hover">\
|
||||
<thead><tr>'+thead+'</tr></thead>\
|
||||
<tbody>'+tbody+'</tbody>\
|
||||
</table>\
|
||||
</div>'
|
||||
});
|
||||
}
|
||||
|
||||
function pgInitField(f, data){
|
||||
var option_html = '<option value="0">无字段</option>';
|
||||
for (var i = 0; i < f.length; i++){
|
||||
if (data['soso_field'] == f[i]){
|
||||
option_html += '<option value="'+pgHtml(f[i])+'" selected>'+pgHtml(f[i])+'</option>';
|
||||
} else {
|
||||
option_html += '<option value="'+pgHtml(f[i])+'">'+pgHtml(f[i])+'</option>';
|
||||
}
|
||||
}
|
||||
$('#postgresql select[name="postgresql_field_key"]').html(option_html);
|
||||
}
|
||||
|
||||
function initTabPostgresql(){
|
||||
clearInterval(pg_timer);
|
||||
pg_last_error = '';
|
||||
|
||||
pgGetServerList(function(){
|
||||
pgGetDbList();
|
||||
pgProcessList();
|
||||
|
||||
clearInterval(pg_timer);
|
||||
pg_timer = setInterval(function(){
|
||||
var name = $('#postgresql_list_tab .tab-nav span.on').data('name');
|
||||
pgRunPgTab(name);
|
||||
|
||||
var fname = $('#cutTab .tabs-item.active').data('name');
|
||||
if (fname != 'postgresql'){
|
||||
clearInterval(pg_timer);
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
$('#postgresql_list_tab .tab-nav span').unbind('click').click(function(){
|
||||
$('#postgresql_list_tab .tab-nav span').removeClass('on');
|
||||
$(this).addClass('on');
|
||||
var name = $(this).data('name');
|
||||
pgRunPgTab(name);
|
||||
});
|
||||
|
||||
$('#postgresql_find').unbind('click').click(function(){
|
||||
var val = $('#postgresql input[name="postgresql_field_value"]').val();
|
||||
if (val == ''){
|
||||
layer.msg('搜索不能为空!',{icon:7});
|
||||
return;
|
||||
}
|
||||
pgGetDataList(1);
|
||||
});
|
||||
|
||||
pgCommonFunc();
|
||||
}
|
||||
|
||||
function pgRunPgTab(name){
|
||||
switch(name){
|
||||
case 'proccess':pgProcessList();break;
|
||||
case 'status':pgStatusList();break;
|
||||
case 'stats':pgStatsList();break;
|
||||
}
|
||||
}
|
||||
|
||||
function pgGetServerList(call_func){
|
||||
closeInstallLayer();
|
||||
pgPostCBN('get_server_list', {}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (data.data && data.data.length != 0){
|
||||
var items = data.data;
|
||||
var content = '';
|
||||
for (var i = 0; i < items.length; i++){
|
||||
var t = items[i];
|
||||
if (i == 0){
|
||||
content += '<option value="'+t['val']+'" selected>'+t['name']+'</option>';
|
||||
} else {
|
||||
content += '<option value="'+t['val']+'">'+t['name']+'</option>';
|
||||
}
|
||||
}
|
||||
|
||||
$('#postgresql select[name=sid]').html(content);
|
||||
$('#postgresql select[name=sid]').change(function(){
|
||||
pgGetDbList();
|
||||
});
|
||||
|
||||
if (typeof(call_func) == 'function'){
|
||||
call_func();
|
||||
}
|
||||
closeInstallLayer();
|
||||
} else {
|
||||
layer.msg('当前未安装 PostgreSQL',{icon:7,time:2000,shade:0.3});
|
||||
setTimeout(function(){
|
||||
showInstallLayer();
|
||||
},2050);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pgGetDbList(){
|
||||
var sid = pgGetSid();
|
||||
pgPostCBN('get_db_list',{'sid':sid}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.data['list'];
|
||||
if (items.length == 0){
|
||||
$('#postgresql .postgresql_db_list select[name=postgresql_db]').html('<option value="0">数据库空</option>');
|
||||
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html('<option value="0">数据表空</option>');
|
||||
$('#postgresql_table thead tr').html('');
|
||||
$('#postgresql_table tbody').html('');
|
||||
$('.postgresql_list_page').html('<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>');
|
||||
return;
|
||||
}
|
||||
|
||||
var content = '';
|
||||
for (var i = 0; i < items.length; i++){
|
||||
var name = items[i];
|
||||
if (i == 0){
|
||||
content += '<option value="'+pgHtml(name)+'" selected>database['+pgHtml(name)+']</option>';
|
||||
} else {
|
||||
content += '<option value="'+pgHtml(name)+'">database['+pgHtml(name)+']</option>';
|
||||
}
|
||||
}
|
||||
|
||||
$('#postgresql .postgresql_db_list select[name=postgresql_db]').html(content);
|
||||
$('#postgresql .postgresql_db_list select[name=postgresql_db]').change(function(){
|
||||
pgGetTableList(1);
|
||||
});
|
||||
|
||||
pgGetTableList(1);
|
||||
});
|
||||
}
|
||||
|
||||
function pgGetTableList(p){
|
||||
var sid = pgGetSid();
|
||||
var db = pgGetDbName();
|
||||
if (!db || db == '0'){
|
||||
return;
|
||||
}
|
||||
|
||||
pgPostCBN('get_table_list',{'sid':sid,'db':db}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.data['list'];
|
||||
if (items.length == 0){
|
||||
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html('<option value="0">数据表空</option>');
|
||||
$('#postgresql_table thead tr').html('');
|
||||
$('#postgresql_table tbody').html('');
|
||||
$('.postgresql_list_page').html('<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>');
|
||||
return;
|
||||
}
|
||||
|
||||
var content = '';
|
||||
for (var i = 0; i < items.length; i++){
|
||||
var name = items[i];
|
||||
if (i == 0){
|
||||
content += '<option value="'+pgHtml(name)+'" selected>table['+pgHtml(name)+']</option>';
|
||||
} else {
|
||||
content += '<option value="'+pgHtml(name)+'">table['+pgHtml(name)+']</option>';
|
||||
}
|
||||
}
|
||||
|
||||
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html(content);
|
||||
$('#postgresql .postgresql_table_list select[name=postgresql_table]').change(function(){
|
||||
pgGetDataList(1);
|
||||
});
|
||||
|
||||
pgGetDataList(1);
|
||||
});
|
||||
}
|
||||
|
||||
function pgGetDataList(p){
|
||||
var sid = pgGetSid();
|
||||
var db = pgGetDbName();
|
||||
var table = pgGetTableName();
|
||||
|
||||
var pg_field = $('#postgresql select[name="postgresql_field_key"]').val();
|
||||
var pg_value = $('#postgresql input[name="postgresql_field_value"]').val();
|
||||
|
||||
var request_data = {
|
||||
'sid': sid,
|
||||
'db': db,
|
||||
'table': table,
|
||||
'p': p,
|
||||
'size': 10
|
||||
};
|
||||
|
||||
if (pg_field != '0' && pg_field){
|
||||
request_data['where'] = {field: pg_field, value: pg_value};
|
||||
} else {
|
||||
request_data['where'] = {};
|
||||
}
|
||||
|
||||
pgPostCB('get_data_list', request_data, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
|
||||
var rdata2 = data.data;
|
||||
var dlist = rdata2['list'];
|
||||
var fields = mongodbGetDataFields(dlist);
|
||||
if (fields.length != 0){
|
||||
pgInitField(fields, rdata2);
|
||||
}
|
||||
|
||||
var header_field = '';
|
||||
for (var i = 0; i < fields.length; i++){
|
||||
header_field += '<th>'+pgHtml(fields[i])+'</th>';
|
||||
}
|
||||
$('#postgresql_table thead tr').html(header_field);
|
||||
|
||||
var tbody = '';
|
||||
for (var i = 0; i < dlist.length; i++){
|
||||
tbody += '<tr>';
|
||||
for (var j = 0; j < fields.length; j++){
|
||||
var f = fields[j];
|
||||
var val = (f in dlist[i]) ? dlist[i][f] : '';
|
||||
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
|
||||
}
|
||||
tbody += '</tr>';
|
||||
}
|
||||
$('#postgresql_table tbody').html(tbody);
|
||||
$('#postgresql .postgresql_list_page').html(rdata2['page']);
|
||||
});
|
||||
}
|
||||
|
||||
function pgRenderOtTable(dlist){
|
||||
var fields = mongodbGetDataFields(dlist);
|
||||
|
||||
var header_field = '';
|
||||
for (var i = 0; i < fields.length; i++){
|
||||
header_field += '<th>'+pgHtml(fields[i])+'</th>';
|
||||
}
|
||||
$('#postgresql_ot_table thead tr').html(header_field);
|
||||
|
||||
var tbody = '';
|
||||
for (var i = 0; i < dlist.length; i++){
|
||||
tbody += '<tr>';
|
||||
for (var j = 0; j < fields.length; j++){
|
||||
var f = fields[j];
|
||||
var val = (f in dlist[i]) ? dlist[i][f] : '';
|
||||
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
|
||||
}
|
||||
tbody += '</tr>';
|
||||
}
|
||||
$('#postgresql_ot_table tbody').html(tbody);
|
||||
}
|
||||
|
||||
function pgProcessList(){
|
||||
pgPostCBN('get_proccess_list',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgToastError(data.msg);
|
||||
return;
|
||||
}
|
||||
pg_last_error = '';
|
||||
pgRenderOtTable(data.data['list']);
|
||||
});
|
||||
}
|
||||
|
||||
function pgStatusList(){
|
||||
pgPostCBN('get_status_list',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgToastError(data.msg);
|
||||
return;
|
||||
}
|
||||
pg_last_error = '';
|
||||
pgRenderOtTable(data.data['list']);
|
||||
});
|
||||
}
|
||||
|
||||
function pgStatsList(){
|
||||
pgPostCBN('get_stats_list',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgToastError(data.msg);
|
||||
return;
|
||||
}
|
||||
pg_last_error = '';
|
||||
pgRenderOtTable(data.data['list']);
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFunc(){
|
||||
$('#postgresql_common').unbind('click').click(function(){
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "PostgreSQL常用功能",
|
||||
area: ['600px', '200px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd20">\
|
||||
<button style="margin-bottom: 8px;" id="pg_top_nsql" type="button" class="btn btn-default btn-sm">查询执行次数最频繁的前N条SQL语句</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_net_stat" type="button" class="btn btn-default btn-sm">PostgreSQL服务器的QPS/TPS指标</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_redundant_indexes" type="button" class="btn btn-default btn-sm">查看重复或冗余的索引</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_table_info" type="button" class="btn btn-default btn-sm">统计库里每个表的大小</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_conn_count" type="button" class="btn btn-default btn-sm">查看应用端IP连接数总和</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_fpk_info" type="button" class="btn btn-default btn-sm">快速找出没有主键的表</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_lock_sql" type="button" class="btn btn-default btn-sm">查看当前锁阻塞的SQL</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_deadlock_info" type="button" class="btn btn-default btn-sm">查看死锁信息</button>\
|
||||
<button style="margin-bottom: 8px;" id="pg_slave_status" type="button" class="btn btn-default btn-sm">查看主从复制信息</button>\
|
||||
</div>',
|
||||
success:function(i,l){
|
||||
$('#pg_top_nsql').click(function(){ pgCommonFuncTopN(); });
|
||||
$('#pg_net_stat').click(function(){ pgCommonFuncNet(); });
|
||||
$('#pg_redundant_indexes').click(function(){ pgCommonFuncRedundantIndexes(); });
|
||||
$('#pg_table_info').click(function(){ pgCommonFuncTableInfo(); });
|
||||
$('#pg_conn_count').click(function(){ pgCommonFuncConnCount(); });
|
||||
$('#pg_fpk_info').click(function(){ pgCommonFuncFpkInfo(); });
|
||||
$('#pg_lock_sql').click(function(){ pgCommonFuncLockSQL(); });
|
||||
$('#pg_deadlock_info').click(function(){ pgCommonFuncDeadlockInfo(); });
|
||||
$('#pg_slave_status').click(function(){ pgCommonFuncSlaveStatus(); });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncTopN(){
|
||||
pgPostCBN('get_topn_list',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgShowNotice('查询执行次数最频繁的前N条SQL语句', data.msg);
|
||||
return;
|
||||
}
|
||||
pgModalTable('查询执行次数最频繁的前N条SQL语句', data.data, '1000px', '450px');
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncNet(){
|
||||
pgPostCBN('get_net_list',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgShowNotice('PostgreSQL服务器的QPS/TPS指标', data.msg);
|
||||
return;
|
||||
}
|
||||
pgModalTable('PostgreSQL服务器的QPS/TPS指标(网络带宽需在系统层监控)', data.data, '1000px', '360px');
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncRedundantIndexes(){
|
||||
function renderList(){
|
||||
pgPostCBN('get_redundant_indexes',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.data;
|
||||
if (items.length == 0){
|
||||
layer.msg('没有发现重复或冗余的索引',{icon:7});
|
||||
return;
|
||||
}
|
||||
|
||||
var tbody = '';
|
||||
for (var i = 0; i < items.length; i++){
|
||||
tbody += '<tr>\
|
||||
<td>'+pgHtml(items[i]['table_schema'])+'</td>\
|
||||
<td>'+pgHtml(items[i]['table_name'])+'</td>\
|
||||
<td>'+pgHtml(items[i]['redundant_index_name'])+'</td>\
|
||||
<td>'+pgHtml(items[i]['redundant_index_columns'])+'</td>\
|
||||
<td><a class="pg_drop_index btlink" index="'+i+'">删除</a></td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "查看重复或冗余的索引",
|
||||
area: ['1000px', '420px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd20 divtable taskdivtable">\
|
||||
<table class="table table-hover" id="pg_redundant_table">\
|
||||
<thead><tr>\
|
||||
<th>库名</th><th>表名</th><th>冗余索引</th><th>字段</th><th>操作</th>\
|
||||
</tr></thead>\
|
||||
<tbody>'+tbody+'</tbody>\
|
||||
</table>\
|
||||
</div>',
|
||||
success: function(){
|
||||
$('#pg_redundant_table .pg_drop_index').click(function(){
|
||||
var index = $(this).attr('index');
|
||||
layer.confirm('确定删除索引 '+pgHtml(items[index]['redundant_index_name'])+' ?', {btn:['确定','取消']}, function(li){
|
||||
pgPostCB('redundant_indexes_cmd', {'sid':pgGetSid(),'index':index}, function(r2){
|
||||
var d = r2.data;
|
||||
showMsg(d.msg,function(){
|
||||
if (d.status){
|
||||
layer.close(li);
|
||||
renderList();
|
||||
}
|
||||
},{icon: d.status ? 1 : 2}, 2000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
renderList();
|
||||
}
|
||||
|
||||
function pgCommonFuncTableInfo(){
|
||||
pgPostCBN('get_table_info',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgShowNotice('统计库里每个表的大小(单位 GB)', data.msg);
|
||||
return;
|
||||
}
|
||||
pgModalTable('统计库里每个表的大小(单位 GB)', data.data, '1200px', '460px');
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncConnCount(){
|
||||
pgPostCBN('get_conn_count',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
pgShowNotice('查看应用端IP连接数总和', data.msg);
|
||||
return;
|
||||
}
|
||||
pgModalTable('查看应用端IP连接数总和', data.data, '700px', '420px');
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncFpkInfo(){
|
||||
pgPostCBN('get_fpk_info',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
pgModalTable('快速找出没有主键的表', data.data, '800px', '400px');
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncLockSQL(){
|
||||
function renderSQL(){
|
||||
pgPostCBN('get_lock_sql',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.data;
|
||||
var tbody = '';
|
||||
for (var i = 0; i < items.length; i++){
|
||||
var t = '<tr>';
|
||||
t += '<td>'+pgHtml(items[i]['trx_id'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['trx_state'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['trx_started'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['processlist_id'])+'</td>';
|
||||
t += '<td title="'+pgHtml(items[i]['info'])+'">'+pgHtml(items[i]['info'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['user'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['host'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['db'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['command'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['state'])+'</td>';
|
||||
t += '<td>'+pgHtml(items[i]['sql_kill_blocking_query'])+'</td>';
|
||||
t += '<td><a class="exec btlink" index="'+i+'">执行</a></td>';
|
||||
t += '</tr>';
|
||||
tbody += t;
|
||||
}
|
||||
$('#pg_lock_table tbody').html(tbody);
|
||||
|
||||
$('#pg_lock_table tbody .exec').click(function(){
|
||||
var index = $(this).attr('index');
|
||||
var pid = items[index]['processlist_id'];
|
||||
pgPostCB('kill_lock_pid', {'sid':pgGetSid(),'pid':pid}, function(r2){
|
||||
var d = r2.data;
|
||||
showMsg(d.msg,function(){
|
||||
if (d.status){
|
||||
renderSQL();
|
||||
}
|
||||
},{icon: d.status ? 1 : 2}, 2000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "查看当前锁阻塞的SQL",
|
||||
area: ['1100px', '420px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd20 divtable taskdivtable">\
|
||||
<div class="mr20 pull-left" style="border-right: 1px solid #ccc; padding-right: 20px;">\
|
||||
<button id="pg_kill_all" type="button" class="btn btn-default btn-sm">关闭所有阻塞</button>\
|
||||
</div>\
|
||||
<hr />\
|
||||
<table class="table table-hover" id="pg_lock_table">\
|
||||
<thead><tr>\
|
||||
<th>事务ID</th><th>事务状态</th><th>执行时间</th><th>线程ID</th>\
|
||||
<th>Info</th><th>user</th><th>host</th><th>db</th>\
|
||||
<th>command</th><th>state</th><th>kill</th><th>操作</th>\
|
||||
</tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table>\
|
||||
</div>',
|
||||
success:function(){
|
||||
renderSQL();
|
||||
$('#pg_kill_all').unbind('click').click(function(){
|
||||
pgPostCB('kill_all_lock', {'sid':pgGetSid()}, function(r2){
|
||||
var d = r2.data;
|
||||
showMsg(d.msg,function(){
|
||||
if (d.status){
|
||||
renderSQL();
|
||||
}
|
||||
},{icon: d.status ? 1 : 2}, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncDeadlockInfo(){
|
||||
function renderText(){
|
||||
pgPostCBN('get_deadlock_info',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
$('#pg_info_log').val(data.data);
|
||||
});
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "查看死锁信息",
|
||||
area: ['800px', '400px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd15">\
|
||||
<textarea readonly="" style="margin: 0px;height: 330px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="pg_info_log"></textarea>\
|
||||
</div>',
|
||||
success:function(){
|
||||
renderText();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pgCommonFuncSlaveStatus(){
|
||||
function renderText(){
|
||||
pgPostCBN('get_slave_status',{'sid':pgGetSid()}, function(rdata){
|
||||
var data = rdata.data;
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:7,time:2500});
|
||||
return;
|
||||
}
|
||||
$('#pg_info_log').val(data.data);
|
||||
});
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "查看主从复制信息",
|
||||
area: ['800px', '400px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form pd15">\
|
||||
<textarea readonly="" style="margin: 0px;height: 330px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="pg_info_log"></textarea>\
|
||||
</div>',
|
||||
success:function(){
|
||||
renderText();
|
||||
}
|
||||
});
|
||||
}
|
||||
// ------------------------- postgresql end ---------------------------------
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ serverPath=$(dirname "$rootPath")
|
||||
VERSION=$2
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
# {
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
Install_Docker()
|
||||
{
|
||||
# which docker
|
||||
# if [ "$?" == "0" ];then
|
||||
# if [ "$?" = "0" ];then
|
||||
# echo '安装已经完成docker'
|
||||
# exit 0
|
||||
# fi
|
||||
@@ -69,7 +69,7 @@ Uninstall_Docker()
|
||||
{
|
||||
CMD=yum
|
||||
which apt
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
CMD=apt
|
||||
fi
|
||||
|
||||
@@ -97,7 +97,7 @@ Uninstall_Docker()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_Docker
|
||||
else
|
||||
Uninstall_Docker
|
||||
|
||||
@@ -135,9 +135,6 @@ def initDreplace():
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
|
||||
|
||||
def appOp(method):
|
||||
initDreplace()
|
||||
if not mw.isAppleSystem():
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"ps": "DNS over HTTPS(DoH)是一种通过HTTPS协议加密域名解析请求的技术!",
|
||||
"name": "doh",
|
||||
"title": "DoH",
|
||||
"versions": ["0.9.15"],
|
||||
"versions": ["0.9.15","0.10.0"],
|
||||
"tip": "soft",
|
||||
"install_pre_inspection":false,
|
||||
"uninstall_pre_inspection":true,
|
||||
|
||||
@@ -9,9 +9,9 @@ Type=simple
|
||||
User=www
|
||||
Group=www
|
||||
WorkingDirectory={$SERVER_PATH}/doh
|
||||
# /www/server/doh/doh-proxy -u 127.0.0.1:53 -l 127.0.0.1:3000
|
||||
# /www/server/doh/doh-proxy -u 127.0.0.1:53 -l 127.0.0.1:3198
|
||||
# /www/server/doh/doh-proxy -h
|
||||
ExecStart={$SERVER_PATH}/doh/doh-proxy -u 127.0.0.1:53 -l 127.0.0.1:3000
|
||||
ExecStart={$SERVER_PATH}/doh/doh-proxy -u 127.0.0.1:53 -l 127.0.0.1:3198
|
||||
Restart=always
|
||||
RemainAfterExit=yes
|
||||
#AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
|
||||
@@ -8,7 +8,7 @@ rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Install_App()
|
||||
echo '正在安装脚本文件...'
|
||||
version=$1
|
||||
|
||||
if [ "macos" == "$OSNAME" ];then
|
||||
if [ "macos" = "$OSNAME" ];then
|
||||
echo "not support!"
|
||||
exit
|
||||
else
|
||||
@@ -59,22 +59,16 @@ Install_App()
|
||||
|
||||
if [ -f $serverPath/source/doh/$file_xz ];then
|
||||
cd $serverPath/source/doh && tar -xjf $file_xz
|
||||
fi
|
||||
|
||||
|
||||
echo "mv $serverPath/source/doh/doh-proxy $serverPath/doh"
|
||||
if [ -f $serverPath/source/doh/doh-proxy ];then
|
||||
echo "mv $serverPath/source/doh/doh-proxy $serverPath/doh"
|
||||
mv $serverPath/source/doh/doh-proxy $serverPath/doh
|
||||
fi
|
||||
|
||||
|
||||
if [ -d $serverPath/doh ];then
|
||||
echo $version > $serverPath/doh/version.pl
|
||||
|
||||
cd ${rootPath} && python3 plugins/doh/index.py start
|
||||
cd ${rootPath} && python3 plugins/doh/index.py initd_install
|
||||
fi
|
||||
|
||||
echo $version > $serverPath/doh/version.pl
|
||||
echo 'install doh success'
|
||||
}
|
||||
|
||||
@@ -95,7 +89,7 @@ Uninstall_App()
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App $version
|
||||
else
|
||||
Uninstall_App $version
|
||||
|
||||
@@ -13,13 +13,13 @@ serverPath=$(dirname "$rootPath")
|
||||
VERSION=$2
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
|
||||
OSNAME=`bash ${rootPath}/scripts/getos.sh`
|
||||
|
||||
if [ "" == "$OSNAME" ];then
|
||||
if [ "" = "$OSNAME" ];then
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
fi
|
||||
|
||||
@@ -83,7 +83,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -106,7 +106,7 @@ def getPidFile():
|
||||
return tmp.groups()[0].strip()
|
||||
|
||||
def status():
|
||||
cmd = "ps aux|grep dztasks|grep -v grep|grep -v python|grep -v mdserver-web|awk '{print $2}'"
|
||||
cmd = "ps -ef|grep dztasks|grep -v grep|grep -v python|grep -v mdserver-web|awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -14,16 +14,16 @@ sysArch=`arch`
|
||||
sysName=`uname`
|
||||
|
||||
DZ_ARCH_NAME=amd64
|
||||
if [ "$sysArch" == "arm64" ];then
|
||||
if [ "$sysArch" = "arm64" ];then
|
||||
DZ_ARCH_NAME=arm64
|
||||
elif [ "$sysArch" == "x86_64" ]; then
|
||||
elif [ "$sysArch" = "x86_64" ]; then
|
||||
DZ_ARCH_NAME=amd64
|
||||
elif [ "$sysArch" == "aarch64" ]; then
|
||||
elif [ "$sysArch" = "aarch64" ]; then
|
||||
DZ_ARCH_NAME=aarch64
|
||||
fi
|
||||
|
||||
DZ_NAME=linux
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
if [ "$sysName" = "Darwin" ];then
|
||||
DZ_NAME=darwin
|
||||
fi
|
||||
Install_App()
|
||||
@@ -78,7 +78,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -328,7 +328,7 @@ def setBlackIp():
|
||||
mw.execShell('fail2ban-client -vvv set {jail} unbanip {ip}'.format(jail=d, ip=ip))
|
||||
|
||||
mw.writeFile(getBlackFile(), json.dumps([]))
|
||||
return nw.returnJson(True, "禁止IP成功")
|
||||
return mw.returnJson(True, "禁止IP成功")
|
||||
|
||||
# 检查IP格式
|
||||
for ip in add_ip_list:
|
||||
|
||||
@@ -67,7 +67,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -3,9 +3,9 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
|
||||
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" = "$1"; }
|
||||
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" = "$1"; }
|
||||
|
||||
# cd /www/server/mdserver-web/plugins/gdrive && /bin/bash install.sh install 2.0
|
||||
|
||||
@@ -22,7 +22,7 @@ PATH=$PATH:${rootPath}/bin
|
||||
export PATH
|
||||
|
||||
# if [ -f ${rootPath}/bin/activate ];then
|
||||
# source ${rootPath}/bin/activate
|
||||
# . ${rootPath}/bin/activate
|
||||
# fi
|
||||
|
||||
VERSION=$2
|
||||
@@ -43,9 +43,9 @@ Install_App()
|
||||
echo "python3 < 3.10"
|
||||
cd ${GDDIR} && python3 -m venv .
|
||||
fi
|
||||
cd ${GDDIR} && source ${GDDIR}/bin/activate
|
||||
cd ${GDDIR} && . ${GDDIR}/bin/activate
|
||||
else
|
||||
cd ${GDDIR} && source ${GDDIR}/bin/activate
|
||||
cd ${GDDIR} && . ${GDDIR}/bin/activate
|
||||
fi
|
||||
|
||||
tmp=`python3 -V 2>&1|awk '{print $2}'`
|
||||
@@ -101,7 +101,7 @@ action=$1
|
||||
type=$2
|
||||
|
||||
echo $action $type
|
||||
if [ "${action}" == 'install' ];then
|
||||
if [ "${action}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"ps": "Gitea是一个开源社区驱动的轻量级代码托管解决方案。",
|
||||
"name": "gitea",
|
||||
"title": "Gitea",
|
||||
"versions": ["1.17.2","1.18.5","1.22.1","1.24.3"],
|
||||
"versions": ["1.17.2","1.18.5","1.22.1","1.24.3","1.25.3"],
|
||||
"tip": "soft",
|
||||
"install_pre_inspection":false,
|
||||
"uninstall_pre_inspection":true,
|
||||
|
||||
@@ -2,16 +2,22 @@
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
# cd /www/server/mdserver-web/plugins/gitea && bash install.sh upgrade 1.25.3
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
|
||||
|
||||
URL_DOWNLOAD=https://dl.gitea.com
|
||||
|
||||
|
||||
@@ -25,11 +31,11 @@ getBit(){
|
||||
}
|
||||
|
||||
Install_Rsync(){
|
||||
if [ "$OSNAME" == "debian" ] || [ "$OSNAME" == "ubuntu" ];then
|
||||
if [ "$OSNAME" = "debian" ] || [ "$OSNAME" = "ubuntu" ];then
|
||||
apt install -y rsync
|
||||
elif [[ "$OSNAME" == "arch" ]]; then
|
||||
elif [[ "$OSNAME" = "arch" ]]; then
|
||||
echo y | pacman -Sy rsync
|
||||
elif [[ "$OSNAME" == "macos" ]]; then
|
||||
elif [[ "$OSNAME" = "macos" ]]; then
|
||||
# brew install rsync
|
||||
# brew install lsyncd
|
||||
echo "ok"
|
||||
@@ -66,7 +72,7 @@ Install_App()
|
||||
|
||||
git config --global push.default simple
|
||||
|
||||
if [ "macos" == "$OSNAME" ];then
|
||||
if [ "macos" = "$OSNAME" ];then
|
||||
file=gitea-${version}-darwin-10.12-amd64
|
||||
else
|
||||
file=gitea-${version}-linux-amd64
|
||||
@@ -87,20 +93,21 @@ Install_App()
|
||||
chown -R www:www $serverPath/gitea
|
||||
fi
|
||||
|
||||
|
||||
if [ -d $serverPath/gitea ];then
|
||||
echo $version > $serverPath/gitea/version.pl
|
||||
|
||||
if [ -d $serverPath/gitea ] && [ "${action}" = 'install' ] ;then
|
||||
cd ${rootPath} && python3 plugins/gitea/index.py start
|
||||
cd ${rootPath} && python3 plugins/gitea/index.py initd_install
|
||||
fi
|
||||
|
||||
echo $version > $serverPath/gitea/version.pl
|
||||
echo 'install success'
|
||||
|
||||
if [ "$action" = "upgrade" ];then
|
||||
which systemctl && systemctl restart gitea
|
||||
fi
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
{
|
||||
|
||||
if [ -f /usr/lib/systemd/system/gitea.service ];then
|
||||
systemctl stop gitea
|
||||
systemctl disable gitea
|
||||
@@ -116,11 +123,10 @@ Uninstall_App()
|
||||
echo 'uninstall success'
|
||||
}
|
||||
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${action}" = 'install' ] || [ "$action" = "upgrade" ];then
|
||||
Install_App $version
|
||||
else
|
||||
elif [ "${action}" = 'uninstall' ];then
|
||||
Uninstall_App $version
|
||||
else
|
||||
echo "OPTIONS ERROR"
|
||||
fi
|
||||
|
||||
@@ -8,7 +8,7 @@ rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ GOGS_DOWNLOAD='https://dl.gogs.io'
|
||||
|
||||
getOs(){
|
||||
os=`uname`
|
||||
if [ "Darwin" == "$os" ];then
|
||||
if [ "Darwin" = "$os" ];then
|
||||
echo 'darwin'
|
||||
else
|
||||
echo 'linux'
|
||||
@@ -48,7 +48,7 @@ Install_gogs()
|
||||
|
||||
git config --global push.default simple
|
||||
|
||||
if [ "darwin" == "$os" ];then
|
||||
if [ "darwin" = "$os" ];then
|
||||
file=gogs_${version}_darwin_amd64.zip
|
||||
else
|
||||
file=gogs_${version}_linux_amd64.zip
|
||||
@@ -100,7 +100,7 @@ Uninstall_gogs()
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_gogs $version
|
||||
else
|
||||
Uninstall_gogs $version
|
||||
|
||||
@@ -113,7 +113,7 @@ def status():
|
||||
# if not os.path.exists(pid_file):
|
||||
# return 'stop'
|
||||
|
||||
cmd = "ps aux|grep gorse |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
cmd = "ps -ef|grep gorse |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
|
||||
if data[0] == '':
|
||||
|
||||
@@ -21,16 +21,16 @@ Install_App()
|
||||
mkdir -p $serverPath/source/gorse
|
||||
|
||||
SYSNAME=linux
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
if [ "$sysName" = "Darwin" ];then
|
||||
SYSNAME=darwin
|
||||
fi
|
||||
|
||||
ARCH="amd64"
|
||||
if [ "$sysArch" == "x86_64" ];then
|
||||
if [ "$sysArch" = "x86_64" ];then
|
||||
ARCH="amd64"
|
||||
elif [ "$sysArch" == "aarch64" ];then
|
||||
elif [ "$sysArch" = "aarch64" ];then
|
||||
ARCH="arm64"
|
||||
elif [ "$sysArch" == "arm64" ];then
|
||||
elif [ "$sysArch" = "arm64" ];then
|
||||
ARCH="arm64"
|
||||
else
|
||||
ARCH="amd64"
|
||||
@@ -88,7 +88,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -84,7 +84,7 @@ def getPidFile():
|
||||
return tmp.groups()[0].strip()
|
||||
|
||||
def status():
|
||||
cmd = "ps aux|grep grafana |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
cmd = "ps -ef|grep grafana |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -18,17 +18,17 @@ sysName=`uname`
|
||||
echo "use system: ${sysName}"
|
||||
|
||||
OSNAME=`bash ${rootPath}/scripts/getos.sh`
|
||||
if [ "" == "$OSNAME" ];then
|
||||
if [ "" = "$OSNAME" ];then
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
fi
|
||||
|
||||
if [ "macos" == "$OSNAME" ];then
|
||||
if [ "macos" = "$OSNAME" ];then
|
||||
echo "不支持Macox"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
if id grafana &> /dev/null ;then
|
||||
@@ -78,7 +78,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -17,11 +17,11 @@ sysArch=`arch`
|
||||
sysName=`uname`
|
||||
|
||||
ARCH_NAME=amd64
|
||||
if [ "$sysArch" == "arm64" ];then
|
||||
if [ "$sysArch" = "arm64" ];then
|
||||
ARCH_NAME=arm64
|
||||
elif [ "$sysArch" == "x86_64" ]; then
|
||||
elif [ "$sysArch" = "x86_64" ]; then
|
||||
ARCH_NAME=amd64
|
||||
elif [ "$sysArch" == "aarch64" ]; then
|
||||
elif [ "$sysArch" = "aarch64" ]; then
|
||||
ARCH_NAME=aarch64
|
||||
fi
|
||||
|
||||
@@ -54,7 +54,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=${1}
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -22,7 +22,7 @@ else
|
||||
useradd -g haproxy haproxy
|
||||
fi
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
if [ "${2}" = "" ];then
|
||||
echo '缺少安装脚本...'
|
||||
exit 0
|
||||
fi
|
||||
@@ -32,7 +32,7 @@ if [ ! -d $curPath/versions/$2 ];then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${action}" == "uninstall" ];then
|
||||
if [ "${action}" = "uninstall" ];then
|
||||
|
||||
if [ -f /usr/lib/systemd/system/haproxy.service ] || [ -f /lib/systemd/system/haproxy.service ];then
|
||||
systemctl stop haproxy
|
||||
@@ -45,7 +45,7 @@ fi
|
||||
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
|
||||
if [ "${action}" == "install" ] && [ -d $serverPath/haproxy ];then
|
||||
if [ "${action}" = "install" ] && [ -d $serverPath/haproxy ];then
|
||||
#初始化
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/haproxy/index.py start ${type}
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/haproxy/index.py initd_install ${type}
|
||||
|
||||
@@ -26,12 +26,12 @@ Install_App()
|
||||
|
||||
LOCAL_ADDR=common
|
||||
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then
|
||||
if [ ! -z "$cn" ] || [ "$?" = "0" ] ;then
|
||||
LOCAL_ADDR=cn
|
||||
fi
|
||||
|
||||
|
||||
if [ "${LOCAL_ADDR}" == "cn" ];then
|
||||
if [ "${LOCAL_ADDR}" = "cn" ];then
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://dl.midoks.icu/soft/haproxy/haproxy-${VERSION}.tar.gz
|
||||
fi
|
||||
@@ -39,7 +39,7 @@ Install_App()
|
||||
|
||||
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
if [ $sysName = 'Darwin' ]; then
|
||||
wget --no-check-certificate -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
else
|
||||
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
@@ -53,7 +53,7 @@ Install_App()
|
||||
|
||||
cd ${APP_DIR} && tar -zxvf haproxy-${VERSION}.tar.gz
|
||||
|
||||
if [ "$OSNAME" == "macos" ];then
|
||||
if [ "$OSNAME" = "macos" ];then
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=osx && make install PREFIX=$serverPath/haproxy
|
||||
else
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=linux-glibc && make install PREFIX=$serverPath/haproxy
|
||||
@@ -94,7 +94,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -26,12 +26,12 @@ Install_App()
|
||||
|
||||
LOCAL_ADDR=common
|
||||
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then
|
||||
if [ ! -z "$cn" ] || [ "$?" = "0" ] ;then
|
||||
LOCAL_ADDR=cn
|
||||
fi
|
||||
|
||||
|
||||
if [ "${LOCAL_ADDR}" == "cn" ];then
|
||||
if [ "${LOCAL_ADDR}" = "cn" ];then
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://dl.midoks.icu/soft/haproxy/haproxy-${VERSION}.tar.gz
|
||||
fi
|
||||
@@ -39,7 +39,7 @@ Install_App()
|
||||
|
||||
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
if [ $sysName = 'Darwin' ]; then
|
||||
wget --no-check-certificate -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
else
|
||||
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
@@ -53,7 +53,7 @@ Install_App()
|
||||
|
||||
cd ${APP_DIR} && tar -zxvf haproxy-${VERSION}.tar.gz
|
||||
|
||||
if [ "$OSNAME" == "macos" ];then
|
||||
if [ "$OSNAME" = "macos" ];then
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=osx && make install PREFIX=$serverPath/haproxy
|
||||
else
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=linux-glibc && make install PREFIX=$serverPath/haproxy
|
||||
@@ -94,7 +94,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -26,12 +26,12 @@ Install_App()
|
||||
|
||||
LOCAL_ADDR=common
|
||||
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then
|
||||
if [ ! -z "$cn" ] || [ "$?" = "0" ] ;then
|
||||
LOCAL_ADDR=cn
|
||||
fi
|
||||
|
||||
|
||||
if [ "${LOCAL_ADDR}" == "cn" ];then
|
||||
if [ "${LOCAL_ADDR}" = "cn" ];then
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://dl.midoks.icu/soft/haproxy/haproxy-${VERSION}.tar.gz
|
||||
fi
|
||||
@@ -39,7 +39,7 @@ Install_App()
|
||||
|
||||
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
if [ $sysName = 'Darwin' ]; then
|
||||
wget --no-check-certificate -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
else
|
||||
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
@@ -53,7 +53,7 @@ Install_App()
|
||||
|
||||
cd ${APP_DIR} && tar -zxvf haproxy-${VERSION}.tar.gz
|
||||
|
||||
if [ "$OSNAME" == "macos" ];then
|
||||
if [ "$OSNAME" = "macos" ];then
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=osx && make install PREFIX=$serverPath/haproxy
|
||||
else
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=linux-glibc && make install PREFIX=$serverPath/haproxy
|
||||
@@ -94,7 +94,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -26,12 +26,12 @@ Install_App()
|
||||
|
||||
LOCAL_ADDR=common
|
||||
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then
|
||||
if [ ! -z "$cn" ] || [ "$?" = "0" ] ;then
|
||||
LOCAL_ADDR=cn
|
||||
fi
|
||||
|
||||
|
||||
if [ "${LOCAL_ADDR}" == "cn" ];then
|
||||
if [ "${LOCAL_ADDR}" = "cn" ];then
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://dl.midoks.icu/soft/haproxy/haproxy-${VERSION}.tar.gz
|
||||
fi
|
||||
@@ -39,7 +39,7 @@ Install_App()
|
||||
|
||||
|
||||
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
if [ $sysName = 'Darwin' ]; then
|
||||
wget --no-check-certificate -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
else
|
||||
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
|
||||
@@ -53,7 +53,7 @@ Install_App()
|
||||
|
||||
cd ${APP_DIR} && tar -zxvf haproxy-${VERSION}.tar.gz
|
||||
|
||||
if [ "$OSNAME" == "macos" ];then
|
||||
if [ "$OSNAME" = "macos" ];then
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=osx && make install PREFIX=$serverPath/haproxy
|
||||
else
|
||||
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=linux-glibc && make install PREFIX=$serverPath/haproxy
|
||||
@@ -94,7 +94,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -10,7 +10,7 @@ serverPath=$(dirname "$rootPath")
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
if [ "${2}" = "" ];then
|
||||
echo '缺少安装脚本...'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -21,9 +21,9 @@ ARCH="amd64"
|
||||
|
||||
get_arch() {
|
||||
TMP_ARCH=`arch`
|
||||
if [ "$TMP_ARCH" == "x86_64" ];then
|
||||
if [ "$TMP_ARCH" = "x86_64" ];then
|
||||
ARCH="amd64"
|
||||
elif [ "$TMP_ARCH" == "aarch64" ];then
|
||||
elif [ "$TMP_ARCH" = "aarch64" ];then
|
||||
ARCH="arm64"
|
||||
else
|
||||
echo $ARCH
|
||||
@@ -104,7 +104,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -118,7 +118,7 @@ def configScriptsTpl():
|
||||
|
||||
def status():
|
||||
data = mw.execShell(
|
||||
"ps aux|grep keepalived |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
|
||||
"ps -ef|grep keepalived |grep -v grep | grep -v python| awk '{print $2}'")
|
||||
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -91,7 +91,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -11,7 +11,7 @@ rootPath=$(dirname "$curPath")
|
||||
|
||||
SOFT=$1
|
||||
|
||||
if [ "$SOFT" == "mysql" ];then
|
||||
if [ "$SOFT" = "mysql" ];then
|
||||
bash ${rootPath}/keepalived/scripts/chk_mysql.sh > ${rootPath}/keepalived/keepalived.log
|
||||
else
|
||||
echo "you should use [chk.sh mysql] exp ."
|
||||
|
||||
@@ -11,10 +11,10 @@ serverPath=$(dirname "$rootPath")
|
||||
# cd /www/server/mdserver-web && python3 plugins/lam/index.py start
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
if [ "$sys_os" == "Darwin" ];then
|
||||
if [ "$sys_os" = "Darwin" ];then
|
||||
BAK='_bak'
|
||||
else
|
||||
BAK=''
|
||||
@@ -23,7 +23,7 @@ fi
|
||||
sysName=`uname`
|
||||
echo "use system: ${sysName}"
|
||||
|
||||
if [ "${sysName}" == "Darwin" ]; then
|
||||
if [ "${sysName}" = "Darwin" ]; then
|
||||
OSNAME='macos'
|
||||
elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
|
||||
OSNAME='centos'
|
||||
@@ -83,7 +83,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App $2
|
||||
else
|
||||
Uninstall_App $2
|
||||
|
||||
@@ -115,7 +115,7 @@ def status():
|
||||
return 'stop'
|
||||
|
||||
# data = mw.execShell(
|
||||
# "ps aux|grep redis |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
|
||||
# "ps -ef|grep redis |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
|
||||
|
||||
# if data[0] == '':
|
||||
# return 'stop'
|
||||
|
||||
@@ -38,7 +38,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -37,7 +37,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -91,7 +91,7 @@ def getPidFile():
|
||||
return tmp.groups()[0].strip()
|
||||
|
||||
def status():
|
||||
cmd = "ps aux|grep loki |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
cmd = "ps -ef|grep loki |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
|
||||
@@ -18,17 +18,17 @@ sysName=`uname`
|
||||
echo "use system: ${sysName}"
|
||||
|
||||
OSNAME=`bash ${rootPath}/scripts/getos.sh`
|
||||
if [ "" == "$OSNAME" ];then
|
||||
if [ "" = "$OSNAME" ];then
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
fi
|
||||
|
||||
if [ "macos" == "$OSNAME" ];then
|
||||
if [ "macos" = "$OSNAME" ];then
|
||||
echo "不支持Macox"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
# if id grafana &> /dev/null ;then
|
||||
@@ -77,7 +77,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -17,11 +17,11 @@ sysArch=`arch`
|
||||
sysName=`uname`
|
||||
|
||||
ARCH_NAME=amd64
|
||||
if [ "$sysArch" == "arm64" ];then
|
||||
if [ "$sysArch" = "arm64" ];then
|
||||
ARCH_NAME=arm64
|
||||
elif [ "$sysArch" == "x86_64" ]; then
|
||||
elif [ "$sysArch" = "x86_64" ]; then
|
||||
ARCH_NAME=amd64
|
||||
elif [ "$sysArch" == "aarch64" ]; then
|
||||
elif [ "$sysArch" = "aarch64" ]; then
|
||||
ARCH_NAME=aarch64
|
||||
fi
|
||||
|
||||
@@ -77,7 +77,7 @@ curl -v -H "Content-Type: application/json" -XPOST "http://localhost:3100/loki/
|
||||
-d "{\"streams\": [{\"stream\": {\"test\": \"test\"}, \"values\": [[\"$timestamp\", \"test message\"]]}]}"
|
||||
|
||||
action=${1}
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
@@ -70,7 +70,7 @@ def getConf():
|
||||
|
||||
|
||||
def status():
|
||||
data = mw.execShell("which ipvsadm")
|
||||
data = mw.execShell("command -v ipvsadm")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
@@ -18,7 +18,7 @@ Install_LVS(){
|
||||
mkdir -p $serverPath/source
|
||||
|
||||
which ipvsadm
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
echo '已安装LVS!!'
|
||||
exit 0
|
||||
fi
|
||||
@@ -27,17 +27,17 @@ Install_LVS(){
|
||||
|
||||
# 检测平台命令
|
||||
which apt
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
apt install -y ipvsadm
|
||||
fi
|
||||
|
||||
which yum
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
yum install -y ipvsadm
|
||||
fi
|
||||
|
||||
which ipvsadm
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
echo '正在安装LVS成功!'
|
||||
mkdir -p $serverPath/lvs
|
||||
|
||||
@@ -59,12 +59,12 @@ Uninstall_LVS()
|
||||
{
|
||||
# 检测平台命令
|
||||
which apt
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
apt remove -y ipvsadm
|
||||
fi
|
||||
|
||||
which yum
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$?" = "0" ];then
|
||||
yum uninstall -y ipvsadm
|
||||
fi
|
||||
echo "卸载LVS完成"
|
||||
@@ -75,7 +75,7 @@ Uninstall_LVS()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_LVS
|
||||
else
|
||||
Uninstall_LVS
|
||||
|
||||
@@ -3,17 +3,13 @@ indexer {
|
||||
}
|
||||
|
||||
searchd {
|
||||
listen = 127.0.0.1:9322
|
||||
listen = 127.0.0.1:9322:sphinx
|
||||
listen = 127.0.0.1:9326:mysql
|
||||
listen = 127.0.0.1:9328:http
|
||||
log = /var/log/manticore/searchd.log
|
||||
query_log = /var/log/manticore/query.log
|
||||
pid_file = /var/run/manticore/searchd.pid
|
||||
data_dir = /var/lib/manticore
|
||||
workers = threads
|
||||
binlog_path = /var/lib/manticore
|
||||
max_children = 1000
|
||||
max_matches = 1000000
|
||||
#binlog_path = /var/lib/manticore/binlog
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<p onclick="pluginLogs('manticoresearch','','query_log', 30);">查询日志</p>
|
||||
<p onclick="mcsRunStatus();">运行状态</p>
|
||||
<p onclick="mcsCommonFunc();">常用功能</p>
|
||||
<p onclick="pluginLogsContent('manticoresearch',$('.plugin_version').attr('version'),'systemctl_log');">服务运行日志</p>
|
||||
<p onclick="mcsReadme();">说明</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
|
||||
@@ -141,15 +141,18 @@ def initDreplace():
|
||||
dirs_list = [
|
||||
"/var/log/manticore",
|
||||
"/var/run/manticore",
|
||||
"/var/lib/manticore"
|
||||
"/var/lib/manticore",
|
||||
]
|
||||
|
||||
index_dir = getServerDir() + '/index'
|
||||
dirs_list.append(index_dir)
|
||||
|
||||
for d in dirs_list:
|
||||
if not os.path.exists(d):
|
||||
mw.execShell('mkdir -p ' + d)
|
||||
|
||||
mw.execShell("chown -R manticore:manticore /var/run/manticore")
|
||||
|
||||
mw.execShell("chown -R manticore:manticore "+index_dir)
|
||||
|
||||
# config replace
|
||||
conf_bin = getConf()
|
||||
@@ -205,8 +208,10 @@ def reload():
|
||||
|
||||
|
||||
def rebuild():
|
||||
fixIndexOwner()
|
||||
cmd = 'indexer --all --rotate'
|
||||
data = mw.execShell(cmd)
|
||||
cmd_manticore = asManticore(cmd)
|
||||
data = mw.execShell(cmd_manticore)
|
||||
if data[0].find('successfully')<0:
|
||||
return data[0].replace("\n","<br/>")
|
||||
return 'ok'
|
||||
@@ -273,6 +278,11 @@ def queryLog():
|
||||
tmp = re.search(rep, content)
|
||||
return tmp.groups()[0]
|
||||
|
||||
def systemctlLog():
|
||||
cmd = "journalctl -u manticore -n 15 --no-pager"
|
||||
data = mw.execShell(cmd)
|
||||
return data[0]
|
||||
|
||||
|
||||
def runStatus():
|
||||
s = status()
|
||||
@@ -284,7 +294,7 @@ def runStatus():
|
||||
|
||||
sh = sphinxapi.SphinxClient()
|
||||
port = getMainPort()
|
||||
sh.SetServer('127.0.0.1', port)
|
||||
sh.SetServer('127.0.0.1', int(port))
|
||||
info_status = sh.Status()
|
||||
|
||||
if info_status is None:
|
||||
@@ -320,8 +330,8 @@ def sphinxConfParse():
|
||||
file = getConf()
|
||||
bin_dir = getServerDir()
|
||||
content = mw.readFile(file)
|
||||
rep = r'index\s(.*)'
|
||||
sindex = re.findall(rep, content)
|
||||
rep = r'^index\s+(\w+)'
|
||||
sindex = re.findall(rep, content,re.MULTILINE)
|
||||
indexlen = len(sindex)
|
||||
cmd = {}
|
||||
cmd['cmd'] = "indexer -c " + getConf()
|
||||
@@ -413,6 +423,21 @@ def makeDbToSphinx():
|
||||
return mw.returnJson(True,'测试中')
|
||||
|
||||
|
||||
# 以 manticore 用户执行,避免生成文件属主为 root
|
||||
def asManticore(cmd):
|
||||
if mw.isAppleSystem():
|
||||
return cmd
|
||||
return 'su -s /bin/sh manticore -c "' + cmd + '"'
|
||||
|
||||
|
||||
# 重建前修正索引目录归属,保证 manticore 用户有写权限
|
||||
def fixIndexOwner():
|
||||
index_dir = getServerDir() + '/index'
|
||||
if not os.path.exists(index_dir):
|
||||
return
|
||||
mw.execShell("chown -R manticore:manticore " + index_dir)
|
||||
|
||||
|
||||
# 全量更新
|
||||
def updateAll():
|
||||
data = sphinxConfParse()
|
||||
@@ -421,10 +446,12 @@ def updateAll():
|
||||
return '无更新'
|
||||
index = data['index']
|
||||
|
||||
fixIndexOwner()
|
||||
for x in range(len(index)):
|
||||
cmd_index = cmd + ' ' + index[x]['index'] + ' --rotate'
|
||||
subprocess.run(asManticore(cmd_index), shell=True)
|
||||
print(cmd_index)
|
||||
os.system(cmd_index)
|
||||
|
||||
return ''
|
||||
|
||||
#增量更新
|
||||
@@ -435,15 +462,16 @@ def updateDelta():
|
||||
return '无更新'
|
||||
index = data['index']
|
||||
|
||||
fixIndexOwner()
|
||||
for x in range(len(index)):
|
||||
if 'delta' in index[x]:
|
||||
cmd_index = cmd + ' ' + index[x]['delta'] + ' --rotate'
|
||||
subprocess.run(asManticore(cmd_index), shell=True)
|
||||
print(cmd_index)
|
||||
os.system(cmd_index)
|
||||
|
||||
cmd_index_merge = cmd + ' --merge ' + index[x]['index'] + ' ' + index[x]['delta'] + ' --rotate'
|
||||
subprocess.run(asManticore(cmd_index_merge), shell=True)
|
||||
print(cmd_index_merge)
|
||||
os.system(cmd_index_merge)
|
||||
else:
|
||||
print(index[x]['index'],'no delta')
|
||||
|
||||
@@ -491,6 +519,8 @@ if __name__ == "__main__":
|
||||
print(runLog())
|
||||
elif func == 'query_log':
|
||||
print(queryLog())
|
||||
elif func == 'systemctl_log':
|
||||
print(systemctlLog())
|
||||
elif func == 'run_status':
|
||||
print(runStatus())
|
||||
elif func == 'run_status_test':
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "manticoresearch",
|
||||
"title": "manticoresearch",
|
||||
"shell": "install.sh",
|
||||
"versions":["7.4.6"],
|
||||
"versions":["debian", "code", "latest"],
|
||||
"tip": "soft",
|
||||
"install_pre_inspection":true,
|
||||
"checks": "server/manticoresearch",
|
||||
|
||||
15
plugins/manticoresearch/init.d/manticore.service.tpl
Normal file
15
plugins/manticoresearch/init.d/manticore.service.tpl
Normal file
@@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Manticore Search
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=manticore
|
||||
Group=manticore
|
||||
ExecStart=/usr/local/bin/searchd -c /etc/manticoresearch/manticore.conf
|
||||
ExecStop=/usr/local/bin/searchd -c /etc/manticoresearch/manticore.conf --stopwait
|
||||
Restart=on-failure
|
||||
LimitNOFILE=65536
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -9,25 +9,36 @@ serverPath=$(dirname "$rootPath")
|
||||
sysName=`uname`
|
||||
sysArch=`arch`
|
||||
|
||||
# cd /www/server/mdserver-web/plugins/manticoresearch && bash install.sh install 7.4.6
|
||||
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/manticoresearch && bash install.sh install latest
|
||||
# cd /www/server/mdserver-web/plugins/manticoresearch && bash install.sh install code
|
||||
# cd /www/server/mdserver-web/plugins/manticoresearch && bash install.sh install latest
|
||||
# cd /www/server/mdserver-web && python3 plugins/manticoresearch/index.py run_status_test
|
||||
# cd /www/server/mdserver-web && python3 plugins/manticoresearch/index.py start
|
||||
|
||||
# su -s /bin/sh manticore -c "indexer -c /etc/manticoresearch/manticore.conf xx --rotate"
|
||||
# su -s /bin/sh manticore -c "indexer -c /etc/manticoresearch/manticore.conf xx_delta --rotate"
|
||||
|
||||
# systemctl status manticore
|
||||
# systemctl restart manticore
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
ACTION=$1
|
||||
VERSION=$2
|
||||
|
||||
which apt
|
||||
if [ "$?" == "0" ];then
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
sh -x $curPath/versions/mac/install.sh $1 $2
|
||||
elif [ "$VERSION" == "code" ];then
|
||||
sh -x $curPath/versions/source/install.sh $1 $2
|
||||
elif [ "$VERSION" == "debian" ];then
|
||||
sh -x $curPath/versions/apt/install.sh $1 $2
|
||||
fi
|
||||
|
||||
which yum
|
||||
if [ "$?" == "0" ];then
|
||||
elif command -v apt >/dev/null 2>&1;then
|
||||
sh -x $curPath/versions/apt/install.sh $1 $2
|
||||
elif command -v yum >/dev/null 2>&1;then
|
||||
sh -x $curPath/versions/yum/install.sh $1 $2
|
||||
else
|
||||
echo "unsupported system: ${sysName}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -98,8 +98,8 @@ logs_file=$plugin_path/${rname}.log
|
||||
''' % (mw_dir, name, getServerDir(), getPluginDir())
|
||||
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
|
||||
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
|
||||
cmd += 'echo "python3 $script_path/index.py update_all"' + "\n"
|
||||
cmd += 'cd $mw_dir && python3 $script_path/index.py update_all' + "\n"
|
||||
cmd += 'cd $mw_dir && . bin/activate && python3 plugins/manticoresearch/index.py update_all' + "\n"
|
||||
cmd += 'echo "cd $mw_dir && . bin/activate && python3 plugins/manticoresearch/index.py update_all"' + "\n"
|
||||
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
|
||||
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
|
||||
|
||||
@@ -147,8 +147,8 @@ logs_file=$plugin_path/${rname}.log
|
||||
''' % (mw_dir, name, getServerDir(), getPluginDir())
|
||||
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
|
||||
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
|
||||
cmd += 'echo "python3 $script_path/index.py update_delta"' + "\n"
|
||||
cmd += 'cd $mw_dir && python3 $script_path/index.py update_delta' + "\n"
|
||||
cmd += 'cd $mw_dir && . bin/activate && python3 plugins/manticoresearch/index.py update_delta' + "\n"
|
||||
cmd += 'echo "cd $mw_dir && . bin/activate && python3 plugins/manticoresearch/index.py update_delta"' + "\n"
|
||||
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
|
||||
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
searchd {
|
||||
listen = 127.0.0.1:9322
|
||||
listen = 127.0.0.1:9322:sphinx
|
||||
listen = 127.0.0.1:9326:mysql
|
||||
listen = 127.0.0.1:9328:http
|
||||
log = /var/log/manticore/searchd.log
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
searchd {
|
||||
listen = 127.0.0.1:9322
|
||||
listen = 127.0.0.1:9322:sphinx
|
||||
listen = 127.0.0.1:9326:mysql
|
||||
listen = 127.0.0.1:9328:http
|
||||
log = /var/log/manticore/searchd.log
|
||||
query_log = /var/log/manticore/query.log
|
||||
pid_file = /var/run/manticore/searchd.pid
|
||||
data_dir = /var/lib/manticore
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ sysName=`uname`
|
||||
sysArch=`arch`
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
VERSION=$2
|
||||
@@ -23,21 +23,23 @@ Install_App()
|
||||
MC_DIR=${serverPath}/source/manticoresearch
|
||||
mkdir -p $MC_DIR
|
||||
|
||||
# wget --no-check-certificate -O /www/server/source/manticoresearch/manticore-repo.noarch.deb https://repo.manticoresearch.com/manticore-repo.noarch.deb
|
||||
# cd /www/server/source/manticoresearch/ && dpkg -i manticore-repo.noarch.deb
|
||||
wget --no-check-certificate -O $MC_DIR/manticore-repo.noarch.deb https://repo.manticoresearch.com/manticore-repo.noarch.deb
|
||||
dpkg -i $MC_DIR/manticore-repo.noarch.deb
|
||||
apt update -y
|
||||
apt -y install manticore manticore-extra
|
||||
|
||||
apt -y install manticore
|
||||
apt -y install manticore-extra
|
||||
apt -y upgrade manticore
|
||||
|
||||
echo "${VERSION}" > $serverPath/manticoresearch/version.pl
|
||||
|
||||
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py start ${VERSION}
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py initd_install ${VERSION}
|
||||
|
||||
if [ -d ${MC_DIR} ];then
|
||||
rm -rf ${MC_DIR}
|
||||
fi
|
||||
# if [ -d ${MC_DIR} ];then
|
||||
# rm -rf ${MC_DIR}
|
||||
# fi
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
@@ -45,7 +47,8 @@ Uninstall_App()
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py stop ${VERSION}
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py initd_uninstall ${VERSION}
|
||||
|
||||
apt -y remove manticore manticore-extra
|
||||
apt -y remove manticore
|
||||
apt -y remove manticore-extra
|
||||
apt -y autoremove
|
||||
|
||||
if [ -d $serverPath/manticoresearch ];then
|
||||
@@ -64,7 +67,7 @@ Uninstall_App()
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
if [ "${1}" = 'install' ];then
|
||||
Install_App
|
||||
else
|
||||
Uninstall_App
|
||||
|
||||
166
plugins/manticoresearch/versions/mac/install.sh
Normal file
166
plugins/manticoresearch/versions/mac/install.sh
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
|
||||
export PATH
|
||||
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sysName=`uname`
|
||||
sysArch=`arch`
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
. ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
VERSION=$2
|
||||
action=$1
|
||||
|
||||
if [ "${VERSION}" = "latest" ] || [ -z "${VERSION}" ];then
|
||||
VERSION=$(curl -fsSL https://api.github.com/repos/manticoresoftware/manticoresearch/releases/latest 2>/dev/null | grep -o '"tag_name": *"release-[^"]*"' | head -n 1 | sed 's/.*release-//;s/"//')
|
||||
if [ -z "${VERSION}" ];then
|
||||
VERSION=29.9.0
|
||||
fi
|
||||
fi
|
||||
|
||||
# 下载文件,直连失败时走加速镜像
|
||||
download_file()
|
||||
{
|
||||
src=$1
|
||||
dst=$2
|
||||
for url in "$src" "https://ghproxy.net/$src" "https://gh-proxy.com/$src" "https://ghfast.top/$src"
|
||||
do
|
||||
if curl -fsSL --retry 2 --connect-timeout 20 -o "$dst" "$url";then
|
||||
return 0
|
||||
fi
|
||||
rm -f "$dst"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
Install_App()
|
||||
{
|
||||
echo '正在安装manticoresearch...'
|
||||
mkdir -p $serverPath/manticoresearch
|
||||
|
||||
MC_DIR=${serverPath}/source/manticoresearch
|
||||
mkdir -p $MC_DIR
|
||||
|
||||
# https://github.com/manticoresoftware/manticoresearch/archive/refs/tags/release-29.9.0.tar.gz
|
||||
MC_SRC=$MC_DIR/manticoresearch-release-${VERSION}
|
||||
if [ ! -d $MC_SRC ];then
|
||||
# 必须带 --recursive,否则缺少 mcl 子模块会导致 cmake 失败
|
||||
if ! git clone --depth 1 --branch release-${VERSION} --recursive \
|
||||
https://github.com/manticoresoftware/manticoresearch.git $MC_SRC;then
|
||||
rm -rf $MC_SRC
|
||||
if [ ! -f $MC_DIR/release-${VERSION}.tar.gz ];then
|
||||
download_file "https://github.com/manticoresoftware/manticoresearch/archive/refs/tags/release-${VERSION}.tar.gz" $MC_DIR/release-${VERSION}.tar.gz
|
||||
fi
|
||||
cd $MC_DIR && tar -zxvf release-${VERSION}.tar.gz
|
||||
fi
|
||||
fi
|
||||
|
||||
# 源码包方式没有子模块,单独补全 mcl(子模块地址见 .gitmodules: manticoresoftware/columnar)
|
||||
if [ ! -f $MC_SRC/mcl/CMakeLists.txt ];then
|
||||
echo 'initializing mcl submodule...'
|
||||
rm -rf $MC_SRC/mcl
|
||||
MCL_SHA=$(curl -fsSL "https://api.github.com/repos/manticoresoftware/manticoresearch/contents/mcl?ref=release-${VERSION}" 2>/dev/null | grep -o '"sha": *"[0-9a-f]*"' | head -n 1 | sed 's/.*"sha": *"//;s/"//')
|
||||
if ! git clone https://github.com/manticoresoftware/columnar.git $MC_SRC/mcl;then
|
||||
echo "mcl clone failed!"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "${MCL_SHA}" ];then
|
||||
cd $MC_SRC/mcl && git checkout ${MCL_SHA}
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f $MC_SRC/mcl/CMakeLists.txt ];then
|
||||
echo "MCL submodule is required at $MC_SRC/mcl."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 预先下载 CRoaring,避免 cmake FetchContent 直连 github 下载失败
|
||||
ROARING_VER=4.3.2
|
||||
ROARING_SRC=$MC_DIR/deps/CRoaring-${ROARING_VER}
|
||||
if [ ! -d $ROARING_SRC ];then
|
||||
mkdir -p $MC_DIR/deps
|
||||
ROARING_TGZ=$MC_DIR/deps/roaring-v${ROARING_VER}.tar.gz
|
||||
if [ ! -s $ROARING_TGZ ];then
|
||||
if ! download_file "https://github.com/RoaringBitmap/CRoaring/archive/refs/tags/v${ROARING_VER}.tar.gz" "$ROARING_TGZ";then
|
||||
echo "roaring download failed!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
tar -zxvf $ROARING_TGZ -C $MC_DIR/deps
|
||||
fi
|
||||
|
||||
if [ ! -f $ROARING_SRC/CMakeLists.txt ];then
|
||||
echo "roaring source is required at $ROARING_SRC."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 上次配置失败残留的 build 目录会保留 FetchContent 失败状态,先清理
|
||||
if [ -d $MC_SRC/build ] && [ ! -f $MC_SRC/build/Makefile ];then
|
||||
rm -rf $MC_SRC/build
|
||||
fi
|
||||
|
||||
mkdir -p $MC_SRC/build
|
||||
cd $MC_SRC/build
|
||||
cmake .. -DBOOST_ROOT="$(brew --prefix boost)" \
|
||||
-DCMAKE_PREFIX_PATH="$(brew --prefix boost);$(brew --prefix icu4c@79);$(brew --prefix openssl@3)" \
|
||||
-DICU_ROOT="$(brew --prefix icu4c@79)" \
|
||||
-DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3)" \
|
||||
-DFETCHCONTENT_SOURCE_DIR_ROARING="$ROARING_SRC" \
|
||||
-DDISTR=macos \
|
||||
-DWITH_GALERA=OFF
|
||||
if [ ! -f Makefile ];then
|
||||
echo "manticoresearch cmake configure failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JOBS=$(sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
if ! make -j${JOBS};then
|
||||
echo "manticoresearch build failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "${VERSION}" > $serverPath/manticoresearch/version.pl
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py start ${VERSION}
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py initd_install ${VERSION}
|
||||
|
||||
|
||||
# if [ -d $MC_DIR/manticoresearch-release-${VERSION} ];then
|
||||
# rm -rf $MC_DIR/manticoresearch-release-${VERSION}
|
||||
# fi
|
||||
echo "install manticoresearch successful!"
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
{
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py stop ${VERSION}
|
||||
cd ${rootPath} && python3 plugins/manticoresearch/index.py initd_uninstall ${VERSION}
|
||||
|
||||
if [ -d $serverPath/manticoresearch ];then
|
||||
rm -rf $serverPath/manticoresearch
|
||||
fi
|
||||
|
||||
if [ -f /usr/lib/systemd/system/manticore.service ] || [ -f /lib/systemd/system/manticore.service ];then
|
||||
systemctl stop manticore
|
||||
systemctl disable manticore
|
||||
rm -rf /usr/lib/systemd/system/manticore.service
|
||||
rm -rf /lib/systemd/system/manticore.service
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
echo "uninstall manticoresearch successful!"
|
||||
}
|
||||
|
||||
if [ "${1}" = 'install' ] || [ "$action" = "upgrade" ];then
|
||||
Install_App
|
||||
elif [ "${1}" = 'uninstall' ];then
|
||||
Uninstall_App
|
||||
else
|
||||
echo "OPTIONS ERROR"
|
||||
fi
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user