问下星球宝石星球更新你怎么登录进去的,密码有什么格式0.0

问下宝石星球的密码格式怎么设置,感谢啦_百度知道
问下宝石星球的密码格式怎么设置,感谢啦
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
小橙子吖橙宝
小橙子吖橙宝
采纳数:27
获赞数:261
擅长:暂未定制
哇!不要这样啦
加了,如何信你
擅长:暂未定制
把软件更新到最新版本就可以了
这样就可以了吗 谢谢啦 么么哒
这样就可以了吗 谢谢啦 么么哒
只要是新版本的就可以了
密码没有格式的
1条折叠回答
为你推荐:
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Xserver的安装及配置
Windows上的Xserver有好几个选择,我用的是,安装时一路默认就可以了。
因为现在很多电脑都有HiDPI,需要对VCXSRV做点设置不然字体会发虚。首先找到软件的安装路径,比如C:\Program Files\VcXsrv,然后对两个可执行文件vcxsrv.exe和xlaunch.exe执行以下操作:
右键点击可执行文件 –& “属性” –& “兼容性” – & “更改高DPI设置” –& “替代高DPI缩放行为”。
在开始菜单查找xlaunch并运行,一路默认就可以开启Xserver。
DISPLAY变量可以放到~/.profile里,当然/etc/profile也是可以的,同时建议设置umask(默认是0000)
umask 0022
export DISPLAY=localhost:0.0
重新打开一个终端或者在当前终端里再export一下就能运行GUI程序了。
先安装中文字体和输入法
sudo apt-get install fonts-wqy-microhei fonts-wqy-zenhei xfonts-wqy
sudo apt-get install fcitx fcitx-pinyin
输入法环境变量可以放到~/.profile
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
再更改dbus配置让fcitx能正常启动。修改/etc/dbus-1/session.conf里的几个配置(如果没有这个文件请自行创建),将
&listen&unix:tmpdir=/tmp&/listen&
&auth&EXTERNAL&/auth&
&listen&tcp:host=localhost,port=0&/listen&
&auth&ANONYMOUS&/auth&
&allow_anonymous/&
最后解决一下Windows输入法和Linux输入法切换冲突问题,把快捷键给错开。这有很多种可能,我采用的方式是关闭Windows的Shift键中英切换,把左Shift让给开关fcitx用,同时关掉fcitx里的输入法循环切换快捷键(因为可选快捷键不够用了……)。具体来讲:
1. Windows: 设置 –& 时间和语言 –& 区域和语言 –& 中文(中华人民共和国)–& 选项 –& 微软输入法 → 按键 –& “中/英文模式切换” 选 “无”
2. Fcitx:用fcitx-configtool打开配置,设置如下
我装了xterm, screen和vim-gtk3
sudo apt-get install xterm screen vim-gtk3
~/.profile中的相关设置如下
export SCREENDIR=$HOME/.screen # 修复screen创建目录的权限问题
xrdb -merge $HOME/.Xresources # xterm使用
最后如果你用VIM的深色主题,可以在.vimrc里设置
以禁用背景色擦写(Background Color Erase)
如果每次启动都要先开xlaunch,再开ubuntu终端,再开程序就太麻烦了。因为我只需要xterm,可以写个vbs来方便开启,脚本如下
set ws=wscript.createobject(&wscript.shell&)
ws.run &&&C:\Program Files\VcXsrv\vcxsrv.exe&& :0 -ac -terminate -lesspointer -multiwindow -clipboard -wgl -silent-dup-error&,0
WScript.Sleep 500
ws.run &C:\Windows\System32\bash.exe -l -c 'export DISPLAY=:0.0; fcitx && /dev/null'&,0,True
WScript.Sleep 500
ws.run &C:\Windows\System32\bash.exe -l -c 'cd $HOME; xterm'&,0
这个脚本先开VCXSRV,再通过bash.exe开fcitx,最后开xterm,中间都有延时。双击就可以运行,最后会弹出xterm的界面。
注意fcitx这里其实很容易出问题,如果没有启动起来只能手动启动了……我想了点办法,但都没什么用。如果你打算装完整的DE,这个问题就容易解决了。
脚本可以放到任何方便的地方,比如“我的文档”,之后要用只需要按Win键,然后输入xterm就能搜到了,再按回车即可启动。
最后补一张图:
June 15, 2018
如何設計一個壞協議
Wed Jun 13 19:44:31 2018
的 slide,
這期冬令營主要內容是協議設計。
冬令營第二講
拋磚引玉,
提出了一個相當簡潔的兩消息隱式帶認證密鑰交換Implicitly Authenticated Key Exchange協議,
後文將稱之爲 BADAKEBasic A-round Diffie-hellman Authenticated Key Exchange。
這是一個相當乾淨的協議,甚至可能大家自己就在實踐中設計過類似的協議。
但這不是一個安全的協議。
slide 中已經舉出了一些該協議的攻擊,這些攻擊並不那麼直觀。
在描述這些攻擊之前,我們先澄清一些定義。
隱式帶認證密鑰交換:
與顯式認證密鑰交換不同,隱式認證協議不會在協議執行中顯式的失敗,
但只有雙方身份正確時會生成相同的密鑰。
認證協議安全要求: 一個合格的認證協議應該在協議完成之後保證
基本僞裝抗性Basic Impersonation Resistance: 若 A 正確執行協議,當敵手不知道 A 的長期密鑰時,敵手不可以僞裝成 A。
密鑰交換協議安全要求: 一個合格的密鑰交換協議應該保證,
完美前向保密Perfect Forward Secrecy: 長期密鑰泄漏時,不會影響之前會話密鑰的安全性。
弱前向保密weak Perfect Forward Secrecy: 由於兩消息的認證密鑰交換協議無可能滿足 PFS,所以對於這些協議,退而求其次,我們只要求 wPFS。
若敵手在長期密鑰泄漏之前沒有參與協議,那長期密鑰泄漏時,不會影響之前會話密鑰的安全性。
已知密鑰安全Known-Key Security: 會話密鑰泄漏時,不會影響長期密鑰及其他會話密鑰的安全性。
臨時祕密揭露抗性Ephemeral Secrets Reveal Resistance: 臨時密鑰泄漏時,不會影響長期密鑰及其他會話密鑰的安全性。
未知密鑰共享Unknown Key-Share抗性: 當 A 和 C 協商出會話密鑰時,A 不會認爲該密鑰是與 B 協商得到的。
Signature + DH
在分析 BADAKE 前,slide 先給出了一個簡單的簽名與密鑰交換的組合協議。
這個協議在簽名中加入了目標身份,以避免交錯攻擊。
但這個協議仍然是不安全的。
當 A 的臨時密鑰 x 泄漏時,
攻擊者可以重放消息 g^x, SIG{A}(g^x, B),與 B 進行握手。
從而達成僞裝 A 身份的目的。
一般情況下防止重放攻擊的最好方案是添加一個 challenge,
但這需要增加一輪通信。
這個例子說明了使用 Signature + DH 的簡單組合無法實現安全的兩消息帶認證密鑰交換。
Implicitly Authenticated DH
slide 給出了 BADAKE 的兩種簡單組合方式。
第一種組合方式相當簡單,
K = H(g^ab, g^xy)
slide 中描述它受到 Open to known key and interleaving attacks 的威脅。
一開始我不太明白這個攻擊如何實現。
我們可以輕鬆找到針對這個協議的多個攻擊方案,這裏我們舉出兩個
A 向 B 發起兩個握手請求,敵手將這兩個請求作爲響應發回給 A。
A 不會知道他正在和自己通信。(呆萌
會話密鑰揭露時的交錯攻擊
這圖片中描述的攻擊與 slide 可能有所不同。
此攻擊需要 B 在握手結束之後泄漏會話密鑰。
B 向 A 發起兩個握手請求,敵手將一個請求作爲響應發回給 B。
兩個會話產生相同的密鑰,結束其中一個會話,B 泄漏會話密鑰 K。
敵手使用該密鑰繼續與 B 通信。
最終達成僞造 A 身份的目的。
KCI Attack
第二種組合方式添加了角色因素,
可以對抗反射、並行會話等攻擊方式。
K = H(g^ab, g^xy, g^x, g^y)
這相比第一種組合方式要好一點,但仍不是一個理想的 AKE 方案。
slide 中提到了密鑰泄漏僞裝攻擊Key-Compromise Impersonation。
簡單來講就是,在 A 的長期密鑰泄漏之後,敵手不但可以僞裝成 A 與 B 通信,也可以僞裝成 B 與 A 通信。
這個漏洞在使用密鑰交換作認證的協議裏很常見,例如
就有這個問題。
很多人會覺得泄漏長期密鑰之後,協議可以不保證認證安全性。但一個好的認證協議應該要避免這一點。
上文的內容在冬令營的演講中只佔不到半分鐘時間,而後面關於 MQV、HMQV 的各種變種佔了將近兩個小時。
設計一個好的密碼協議並不是一件容易的事情。
而想要設計一個壞協議?只需要拍腦袋式的想一個簡潔的協議就可以了。
June 09, 2018
Fortran自从2003以来增加了很多面向对象的特性,尽管和主流OOP语言相比并不完善,但也非常有用。比如可以实现一个通用的哈希表结构,并在此基础上写出类似Python的argparser和configparser等。
这里通过抽象类、多态、继承等实现一个可以存取任何数据对象的栈结构。
使用抽象类定义要存取的数据对象
因为我们希望这个栈能用于任何数据对象,所以先定义一个不包含具体元素的抽象派生类型(即抽象类)
type, abstract :: stack_structure
procedure(copy), deferred :: copy ! copy object.
end type stack_structure
abstract interface
subroutine copy(self, object)
import :: stack_structure
class(stack_structure), intent(in) :: self
class(stack_structure), intent(out) :: object
end subroutine copy
end interface
这里的copy函数是用于pop数据时赋值的。因为我们后面传给stack类的数据都是以支持多态的class(stack_structure)类型传入,stack类并不知道里面的具体数据,因而无法直接赋值,需要迂回一下。
定义stack类
这里只实现两个功能,push和pop。类的定义如下
type :: stack_class
class(stack_structure), pointer :: object =& null()
type(stack_class), pointer :: next =& null()
procedure :: push =& stack_push
procedure :: pop =& stack_pop
final :: stack_cleanup
end type stack_class
在类里面定义了两个私有变量。第一个是存储的数据对象,用的是类指针,可以指向stack_structure及其任意子类,同时也能allocate成任何子类。第二个是指向下一个元素的指针。stack_cleanup是析构函数,用来释放内存等。
先看一下pop函数
subroutine stack_push(self, object)
class(stack_class), intent(inout), target :: self
class(stack_structure), intent(in) :: object
class(stack_class), pointer :: next
if (associated(self%object)) then
next =& self%next
allocate(self%next)
self%next%object =& self%object
self%next%next =& next
allocate(self%object, source=object)
end subroutine stack_push
这里比较关键的一句是
allocate(self%object, source=object)
函数传入object的形参虽然是class(stack_structure),但实参可以是任何stack_structure的子类,上面这句可以直接给self%object分配内存并赋值成object的实参数据,而不需要知道这个实参到底是什么样的。
function stack_pop(self, object) result(success)
class(stack_class), intent(inout), target :: self
class(stack_structure), intent(out) :: object
logical :: success
class(stack_class), pointer :: next
if (.not. associated(self%object)) then
success = .false.
success = .true.
call self%object%copy(object)
deallocate(self%object)
if (associated(self%next)) then
next =& self%next
self%object =& next%object
self%next =& next%next
next%object =& null()
next%next =& null()
deallocate(next)
end function stack_pop
注意指针是否为空需要用associated来判断,但是通过allocate分配内存的指针一定要通过deallocate来释放,否则会内存泄漏。如上面所说,这里使用了copy函数来实现赋值
call self%object%copy(object)
如果采用了对指针类型动态分配内存的方法,一定要记得释放。这里对类里的变量可以通过析构函数来释放
elemental subroutine stack_cleanup(self)
type(stack_class), intent(inout) :: self
if (associated(self%object)) then
deallocate(self%object)
if (associated(self%next)) then
deallocate(self%next)
end subroutine stack_cleanup
定义实际要存取的数据对象
type, extends(stack_structure) :: token_structure
character(len=:), allocatable :: key
procedure :: copy =& token_copy
end type token_structure
interface token_structure
procedure :: token_create_object
end interface token_structure
这里继承了上面的stack_structure定义了一个token_structure,里面存入一个变长字符串。为了方便的生成对象,还定义了构造函数,但不是必要的。
copy函数的实现如下
subroutine token_copy(self, object)
class(token_structure), intent(in) :: self
class(stack_structure), intent(out) :: object
select type(object)
class is(token_structure)
object%key = self%key
end select
end subroutine token_copy
注意object是以stack_structure的类型传入的,必须要用select type判断到token_structure才能赋值。
最后是构造函数
elemental function token_create_object(key) result(token)
character(len=*), intent(in) :: key
type(token_structure) :: token
token%key = trim(adjustl(key))
end function token_create_object
module class_stack
type, abstract :: stack_structure
procedure(copy), deferred :: copy
end type stack_structure
abstract interface
subroutine copy(self, object)
import :: stack_structure
class(stack_structure), intent(in) :: self
class(stack_structure), intent(out) :: object
end subroutine copy
end interface
type :: stack_class
class(stack_structure), pointer :: object =& null()
type(stack_class), pointer :: next =& null()
procedure :: push =& stack_push
procedure :: pop =& stack_pop
final :: stack_cleanup
end type stack_class
subroutine stack_push(self, object)
class(stack_class), intent(inout), target :: self
class(stack_structure), intent(in) :: object
class(stack_class), pointer :: next
if (associated(self%object)) then
next =& self%next
allocate(self%next)
self%next%object =& self%object
self%next%next =& next
allocate(self%object, source=object)
end subroutine stack_push
function stack_pop(self, object) result(success)
class(stack_class), intent(inout), target :: self
class(stack_structure), intent(out) :: object
logical :: success
class(stack_class), pointer :: next
if (.not. associated(self%object)) then
success = .false.
success = .true.
call self%object%copy(object)
deallocate(self%object)
if (associated(self%next)) then
next =& self%next
self%object =& next%object
self%next =& next%next
next%object =& null()
next%next =& null()
deallocate(next)
end function stack_pop
elemental subroutine stack_cleanup(self)
type(stack_class), intent(inout) :: self
if (associated(self%object)) then
deallocate(self%object)
if (associated(self%next)) then
deallocate(self%next)
end subroutine stack_cleanup
end module class_stack
module class_token
use class_stack
type, extends(stack_structure) :: token_structure
character(len=:), allocatable :: key
procedure :: copy =& token_copy
end type token_structure
interface token_structure
procedure :: token_create_object
end interface token_structure
elemental function token_create_object(key) result(token)
character(len=*), intent(in) :: key
type(token_structure) :: token
token%key = trim(adjustl(key))
end function token_create_object
subroutine token_copy(self, object)
class(token_structure), intent(in) :: self
class(stack_structure), intent(out) :: object
select type(object)
class is(token_structure)
object%key = self%key
end select
end subroutine token_copy
end module class_token
program main
use class_stack
use class_token
type(stack_class) :: stack
type(token_structure) :: token
call stack%push(token_structure(&world&))
call stack%push(token_structure(&hello&))
do while(stack%pop(token))
write(*,*) token%key
end program main
派生类型是Fortran很早就支持的特性,默认情况下在作为一个整体进行输入输出时会有一些限制。比如包含allocatable的元素时就不能进行整体输入输出:
type string
character(len=:), allocatable :: s
end type string
type(string) :: zonename
zonename%s = &hello world&
write(*,*) zonename%s
Fortran 2003中加入了用户自定义派生类型IO (User-defined derived-type Input/Output) 的支持,可以突破上面的限制,实现类似下面的效果
type(string) :: scalar
type(string) :: vector(2)
write(*,*) scalar
write(*,*) vector
关于这个特性,很多文档里都有比较好的介绍,比如和。不过我在使用时还是遇到了一点问题,因此记录一下。
一个完整的例子
module class_string
type string
character(len=:), allocatable :: s
generic :: write(formatted) =& formatted_write
procedure, private :: formatted_write
end type string
subroutine formatted_write(self, unit, iotype, vlist, iostat, iomsg)
class(string), intent(in) :: self
integer, intent(in) :: unit
character(len=*), intent(in) :: iotype
integer, dimension(:), intent(in) :: vlist
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
write(unit, &(A)&, advance=&no&, iostat=iostat, iomsg=iomsg) self%s
end subroutine formatted_write
end module class_string
program main
use class_string
type(string) :: vector(2)
vector(1)%s = &hello&
vector(2)%s = &world&
write(*,*) vector
write(*,&(A, 1X, 2(DT, 1X))&) &Formatted&, vector
end program main
在这个例子中,首先对派生类型绑定了用来输入输出的函数
generic :: write(formatted) =& formatted_write
procedure, private :: formatted_write
其中第一行把格式化输出绑定到formatted_write这个私有函数上,第二行定义这个私有函数。
在IBM和Intel的文档中,formatted_write这个函数都是用的List-Directed Formatting输出,这有时不太符合我们的需求。我这里用了显式的格式化输出,并且加入了advance=“no” 以防止输出时加入多余换行。
write(unit, &(A)&, advance=&no&, iostat=iostat, iomsg=iomsg) self%s
最后在使用时,可以用*或者格式化字符串控制输出。
write(*,&(A, 1X, 2(DT, 1X))&) &Formatted&, vector
这句通过格式化字符串输出vector中的两个数组值,其中到单个自定义类型的格式化字符串是“DT”。“2(DT, 1X)“表示数组的每个元素都按DT输出,并且随后跟一个空格,如果没有1X的话”hello”和“world”就会连起来。
June 08, 2018
是比较有名的Graph Partitioning软件,我们一般用来切割计算网格做并行计算。这里稍微记录一下在Fortran中调用的方法和需要注意的问题。
数据类型长度的确定
由于Metis中的整型和实型可以编译为不同的长度,实型通常都是64位,但整型在不同发行版或者平台上可能是32位或者64位。这个地方不对的话就会出现类似下面的错误:
***Memory allocation failed for SetupCtrl: ctrl-&tpwgts.
C可以直接引用metis.h头文件,但Fortran稍微麻烦点(或者有简单方法我不知道)。在metis.h中寻找
define IDXTYPEWIDTH xx
就知道是几位,然后程序中保持一致。
如果你的程序需要适应不同的整型位数,可以在源码里加上预处理。比如
use iso_fortran_env
#if METIS_IDXTYPEWIDTH == 32
integer, parameter :: METIS_INT = INT32
integer, parameter :: METIS_INT = INT64
然后编译的时候指定宏的值,比如
gfortran -cpp -DMETIS_IDXTYPEWIDTH=xx ...
使用Metis函数
以METIS_PartGraphRecursive函数为例(假定使用了上面的预处理定义):
integer(kind=METIS_INT), allocatable, dimension(:) :: xadj
integer(kind=METIS_INT), allocatable, dimension(:) :: adjncy
integer(kind=METIS_INT), allocatable, dimension(:) :: vwgt
integer(kind=METIS_INT), allocatable, dimension(:) :: adjwgt
integer(kind=METIS_INT), allocatable, dimension(:) :: part
integer(kind=METIS_INT), dimension(:), pointer :: ptr =& null() ! Dummy.
integer(kind=METIS_INT) :: nvtxs
integer(kind=METIS_INT) :: nconn
integer(kind=METIS_INT) :: nparts
integer(kind=METIS_INT) :: objval
call METIS_PartGraphRecursive(nvtxs, nconn, xadj, adjncy, vwgt, ptr, adjwgt, nparts, ptr, ptr, ptr, objval, part)
其中可选参数如果不想提供(或接收)的话就用ptr代替。其它变量的具体含义可以看Metis的文档。
注意,Metis默认都是采用C的数组索引(即从0开始),这个行为可以通过传入options数组来改变。但为了防止options的enum值改变(毕竟不能直接用头文件)带来的麻烦,我都是这样做的
! C-style numbering.
xadj = xadj-1
adjncy = adjncy-1
call METIS_PartGraphRecursive(nvtxs, nconn, xadj, adjncy, vwgt, ptr, adjwgt, nparts, ptr, ptr, ptr, objval, part)
! Fortran-style numbering.
part = part+1
xadj = xadj+1
adjncy = adjncy+1
很久没有编辑博客,前几天修改一些内容时发现会有页面空白、500 Internal Error等问题。查看Nginx日志后发现有类似这样的错误
PHP message: PHP Fatal error:
Uncaught Error: Call to undefined function utf8_decode()
主要是一些扩展被分离出去了,成了单独的包。按照Nginx的错误日志,缺什么装什么就可以,以Dokuwiki来说,目前发现需要额外装这两个
aptitude install php-mbstring php-xml
其它分离的包如下(Debian更新日志)
* Several extensions have been split into separate extension packages:
- php-dba - Database (dbm-style) Abstraction Layer
- php-mbstring - Multibyte String
- php-soap - SOAP
- php-xml - DOM, SimpleXML, WDDX, XML, XMLReader and XMLWriter
- php-zip - Zip
June 07, 2018
才不是没东西写了呢
遇到一个奇葩的原因导致 root 分区被占满的。而且还是奇葩的 CentOS,root 分区是 LVM,Hypervisor 里扩展磁盘后无法直接用 resize2fs。
既然如此就只能暴力重建分区咯。
重建分区操作前确保操作的分区和之后新建时 Start 保持一致,修改分区表后不至于分区崩坏。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748~& fidks /dev/sdaWelcome to fdisk (util-linux 2.23.2).Changes will remain in memory only, until you decide to write them.Be careful before using the write command.Command (m for help): pDisk /dev/sda: 103.1 GB,
sectorsUnits = sectors of 1 * 512 = 512 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk label type: dosDisk identifier: 0x000a8e23
Device Boot
System/dev/sda1
Linux/dev/sda2
Linux LVMCommand (m for help): dPartition number (1,2, default 2): 2Partition 2 is deletedCommand (m for help): nPartition type:
primary (1 primary, 0 extended, 3 free)
extendedSelect (default p):Using default response pPartition number (2-4, default 2):First sector (2099200-, default 2099200):Using default value 2099200Last sector, +sectors or +size (2099200-, default ):Using default value Partition 2 of type Linux and of size 95 GiB is setCommand (m for help): wThe partition table has been altered!Calling ioctl() to re-read partition table.WARNING: Re-reading the partition table failed with error 16: Device or resource busy.The kernel still uses the old table. The new table will be used atthe next reboot or after you run partprobe(8) or kpartx(8)Syncing disks.~& partprobe
现在就可以看到 /dev/sda2 的大小已经变化了:
12345678~&
扩展 Volume GroupVG 的好处也就是能够灵活扩展分区大小…
123~& pvresize /dev/sda2
Physical volume "/dev/sda2" changed
1 physical volume(s) resized / 0 physical volume(s) not resized
123456789101112131415161718192021~& vgdisplay
--- Volume group ---
Metadata Areas
Metadata Sequence No
read/write
&95.00 GiB
Alloc PE / Size
5887 / &23.00 GiB
18432 / 72.00 GiB
TpbtuH-AjTZ-PU3v-UN31-FvfX-kSLv-xLiJG7
至此已经可以看到 Free PE 的部分有多出的 72GB 空间。
扩展 Logic Volume12345678910111213~& lvextend -r -l +100%FREE /dev/centos/root
Size of logical volume centos/root changed from 20.59 GiB (5272 extents) to 92.59 GiB (23704 extents).
Logical volume centos/root successfully resized.meta-data=/dev/mapper/centos-root isize=512
agcount=4, agsize=1349632 blks
sectsz=512
attr=2, projid32bit=1
finobt=0 spinodes=0data
bsize=4096
blocks=5398528, imaxpct=25
swidth=0 blksnaming
=version 2
bsize=4096
ascii-ci=0 ftype=1log
bsize=4096
blocks=2636, version=2
sectsz=512
sunit=0 blks, lazy-count=1realtime =none
extsz=4096
blocks=0, rtextents=0data blocks changed from 5398528 to
确认效果:
123456789101112131415161718~& lsblkNAME
MAJ:MIN RM
SIZE RO TYPE MOUNTPOINTsda
0 disk ├─sda1
0 part /boot└─sda2
├─centos-root 253:0
└─centos-swap 253:1
0 rom~& df -hFilesystem
Used Avail Use/dev/mapper/centos-root
23devtmpfs
0/dev/sda1
搞定收工(‘?ω?’)
后话其实虚拟机还用 LVM 的话,直接新增一块虚拟硬盘是最方便的方案。直接 vgextend 一路搞定…才不是没东西写了呢
遇到一个奇葩的原因导致 root 分区被占满的。而且还是奇葩的 CentOS,root 分区是 LVM,Hypervisor 里扩展磁盘后无法直接用 resize2fs。
June 06, 2018
大概就是:
"{{汝设备的代号}}")
-e 's block/xxx xxx ' \
这个样子 ?
那么中间一大把 -e 怎么生成呢?
把汝的手机接到电脑上,运行一下 adb :
$ adb shell
$ shamu:/ $ ls -l /dev/block/platform/
# 在这里按一下 TAB 补全一下:
$ shamu:/ $ ls -l /dev/block/platform/msm_sdcc.1/by-name/
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 aboot -& /dev/block/mmcblk0p7
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 abootBackup -& /dev/block/mmcblk0p13
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 boot -& /dev/block/mmcblk0p37
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 cache -& /dev/block/mmcblk0p38
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 cid -& /dev/block/mmcblk0p29
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 ddr -& /dev/block/mmcblk0p6
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 frp -& /dev/block/mmcblk0p18
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 keystore -& /dev/block/mmcblk0p24
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 kpan -& /dev/block/mmcblk0p36
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 logo -& /dev/block/mmcblk0p30
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 logs -& /dev/block/mmcblk0p25
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1dhob -& /dev/block/mmcblk0p28
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1hob -& /dev/block/mmcblk0p27
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1m9kefs1 -& /dev/block/mmcblk0p19
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1m9kefs2 -& /dev/block/mmcblk0p20
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1m9kefs3 -& /dev/block/mmcblk0p21
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 mdm1m9kefsc -& /dev/block/mmcblk0p33
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 metadata -& /dev/block/mmcblk0p2
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 misc -& /dev/block/mmcblk0p31
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 modem -& /dev/block/mmcblk0p1
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 oem -& /dev/block/mmcblk0p39
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 padA -& /dev/block/mmcblk0p11
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 padB -& /dev/block/mmcblk0p22
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 padC -& /dev/block/mmcblk0p40
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 padD -& /dev/block/mmcblk0p32
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 persist -& /dev/block/mmcblk0p26
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 recovery -& /dev/block/mmcblk0p35
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 rpm -& /dev/block/mmcblk0p8
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 rpmBackup -& /dev/block/mmcblk0p14
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 sbl1 -& /dev/block/mmcblk0p3
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 sbl1bak -& /dev/block/mmcblk0p12
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 sdi -& /dev/block/mmcblk0p4
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 sec -& /dev/block/mmcblk0p5
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 sp -& /dev/block/mmcblk0p23
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 ssd -& /dev/block/mmcblk0p34
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 system -& /dev/block/mmcblk0p41
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 tz -& /dev/block/mmcblk0p10
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 tzBackup -& /dev/block/mmcblk0p16
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 userdata -& /dev/block/mmcblk0p42
lrwxrwxrwx 1 root root 20 1970-02-24 06:55 utags -& /dev/block/mmcblk0p9
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 utagsBackup -& /dev/block/mmcblk0p15
lrwxrwxrwx 1 root root 21 1970-02-24 06:55 versions -& /dev/block/mmcblk0p17
以第一行为例,大概可以这样写:
-e 's block/platform/msm_sdcc.1/by-name/aboot mmcblk0p7 '
以此类推,可以考虑写个脚本简化这一过程,不过记住最后的反斜线后面应该是啥都没有的 ?
(说多了都是眼泪啊……)
设置相应的环境变量:
# 就是汝上一节写的那个啦
$ source ~/.hadk.env
$ cd $ANDROID_ROOT
# 换 python2
$ source venv/bin/activate
# 如果硬盘够用的话,可以考虑用 ccache 缓存中间文件加速编译
$ export USE_CCACHE=1
# 设置编译 Android 的环境变量
$ source build/envsetup.sh
$ export LC_ALL=C
$ breakfast $DEVICE
然后开始编译:
# 和其它编译类似,可以通过 -j 并行编译提高速度。
$ make -j4 hybris-hal
检查内核配置是否符合 hybris 的需要:
$ hybris/mer-kernel-check/mer_verify_kernel_config ./out/target/product/$DEVICE/obj/KERNEL_OBJ/.config
WARNING: CONFIG_CGROUP_MEM_RES_CTLR_KMEM is invalid
It is unset
Allowed values : y, !
Comment says: systemd (optional): http://0pointer.de/blog/projects/cgroups-vs-cgroups.html
WARNING: CONFIG_SECURITY_SELINUX_BOOTPARAM is invalid
It is unset
Allowed values : y, !
Comment says: Required by hybris, SELinux needs to be disabled.
Leave as not set, if you have unset AUDIT (read more about the CONFIG_AUDIT flag)
WARNING: CONFIG_CGROUP_MEM_RES_CTLR_SWAP is invalid
It is unset
Allowed values : y, !
Comment says: systemd (optional): http://0pointer.de/blog/projects/cgroups-vs-cgroups.html
WARNING: CONFIG_CGROUP_MEM_RES_CTLR is invalid
It is unset
Allowed values : y, !
Comment says: systemd (optional): http://0pointer.de/blog/projects/cgroups-vs-cgroups.html
WARNING: CONFIG_FW_LOADER_USER_HELPER is invalid
Value is: y
Allowed values : n, !
Comment says: it's actually needed by some Lollipop based devices;
systemd(optional): http://cgit.freedesktop.org/systemd/systemd/commit/README?id=713bc0cfa477ca1dfdbc83c10eace2
可(ken)能(ding)会出一些 ERROR 和 WARNING ,按提示去改汝的 defconfig 去吧……
啥?汝不知道汝的 defconfig 是哪个?这里有几种确定的方法:
$ANDROID_ROOT/device/$VENDOR/*/BoardConfig*.mk 里的 TARGET_KERNEL_CONFIG
或者去 kernel/arch/arm/configs 里按 codename 瞅瞅? ?
编辑完以后 make -j4 hybris-boot 重新生成内核再来一遍。
以及因为内核配置可能有依赖关系和这个检测脚本有点老的缘故,有时汝改了 defconfig 警告还是有 ?,
只要没有 ERROR 多半就 OK ?
如果已经尽力消除所有 ERROR 和大多数 or 全部 WARNING以后,运行 make hybris-recovery 生成恢复内核。
未完待续 *2 ?
June 04, 2018
一部支持 Cyanogenmod/LineageOS 的手机
一台电脑,至少要有 4 GiB 内存和 16 GiB 硬盘的电脑
如果用 ccache 的话需要更多硬盘
当然是多多益善啦~
一个网速 OK 的梯子
咱是在 Parabola GNU/Linux Libre 上编译的,于是 Arch GNU/Linux 应该也可以用。
其它发行版就自行按图索骥好了 ?
安装编译 LineageOS 需要的软件
(因为现在移植到 Android 手机上的 Sailfish OS 是在 Android 上用 hybris 跑起来一个 GNU/Linux 的
用户空间嘛), AUR 上有个 lineageos-devel 的 metapackage。
因为要拖源代码回来,所以装个 git 和 repo ,然后设置一下汝的名称和邮箱(如果汝以前用过 Git 的话可以跳过这一步):
git config --global user.name "Your Name"
git config --global user.email ""
# ~/.hadk.env
# Mer SDK 的位置
export MER_ROOT=/srv/mer
export PLATFORM_SDK_ROOT=$MER_ROOT
# 移植到的目标手机的厂商和代号,可以去 LineageOS Wiki 上找到
export VENDOR="moto"
export DEVICE="shamu"
# 移植的架构,和手机有关
export PORT_ARCH="armv7hl"
# 要移植的 hybris 和 Sailfish OS 版本
export ROOMSERVICE_BRANCHES="cm-14.1"
export HYBRIS_BRANCH="hybris-14.1"
export SAILFISH_VERSION=2.1.4.13
# 源代码放在哪
export ANDROID_ROOT=/home/repo/libhybris
初始化仓库:
$ mkdir -p $ANDROID_ROOT
$ cd $ANDROID_ROOT
$ repo init -u git://github.com/mer-hybris/android.git -b $HYBRIS_BRANCH
设置本地清单,用汝喜欢的文字编辑器打开 $ANDROID_ROOT/.repo/local_manifests
(需要的话就新建一个),然后建立一个 {{汝设备的代号}}.xml ,加入适当的 repo :
至少需要 Device 和 kernel ,在 Github 上搜索一下 “android_[device,kernel]_$VENDOR_$DEVICE”看看?
例如咱的 shamu :
&?xml version="1.0" encoding="UTF-8"?&
&manifest&
&project path="device/moto/shamu" remote="private" name="KenOokamihoro/android_device_moto_shamu"
revision="cm-14.1" /&
&project path="kernel/moto/shamu" remote="private" name="KenOokamiHoro/android_kernel_moto_shamu"
revision="cm-14.1" /&
&project name="TheMuppets/proprietary_vendor_motorola" path="vendor/motorola" revision="cm-14.1"
&project path="rpm/" name="KenOokamiHoro/droid-hal-shamu" revision="master" /&
&project path="hybris/droid-configs" name="KenOokamiHoro/droid-config-shamu" revision="master" /&
&project path="hybris/droid-hal-version-shamu" name="KenOokamiHoro/droid-hal-version-shamu"
revision="master"
&/manifest&
然后同步一下代码:
$ repo sync --fetch-submodules
同步可能需要很长的时间,甚至有可能会失败,失败的话就多试几次 ?
因为 Android 这套工具还认为 python 是 python2 ?
用汝喜欢的虚拟环境工具就 Ok 啦,例如 python2-virtualenv :
$ virtualenv2 /path/to/your/virtualenv
# 以后要用的话:
$ source /path/to/your/virtualenv/bin/activate
从官方文档里抄的 ?
# 下载并解压 SDK 的 chroot
export PLATFORM_SDK_ROOT=/srv/mer
curl -k -O http://releases.sailfishos.org/sdk/installers/latest/Jolla-latest-SailfishOS_Platform_SDK_Chroot-i486.tar.bz2 ;
sudo mkdir -p $PLATFORM_SDK_ROOT/sdks/sfossdk ;
sudo tar --numeric-owner -p -xjf Jolla-latest-SailfishOS_Platform_SDK_Chroot-i486.tar.bz2 -C $PLATFORM_SDK_ROOT/sdks/sfossdk
# 为 .bashrc 设置相应的 PS1 ,alias 和环境变量 (其它 Shell 用户请自行依样画葫芦)
echo "export PLATFORM_SDK_ROOT=$PLATFORM_SDK_ROOT" && ~/.bashrc
echo 'alias sfossdk=$PLATFORM_SDK_ROOT/sdks/sfossdk/mer-sdk-chroot' && ~/.bashrc ; exec bash ;
echo 'PS1="PlatformSDK $PS1"' & ~/.mersdk.profile ;
echo '[ -d /etc/bash_completion.d ] && for i in /etc/bash_completion.d/*;do . $i;done'
&& ~/.mersdk.profile ;
下载工具:
# sdk-assistant create $VENDOR-$DEVICE-xxxx
sdk-assistant create moto-shamu-latest http://releases.sailfishos.org/sdk/latest/Jolla-latest-Sailfish_SDK_Tooling-i486.tar.bz2
# 这一步和汝手机 CPU 的架构相关
sdk-assistant create moto-shamu-armv7hl http://releases.sailfishos.org/sdk/latest/Jolla-latest-Sailfish_SDK_Target-armv7hl.tar.bz2
sdk-assistant create moto-shamu-i486 http://releases.sailfishos.org/sdk/latest/Jolla-latest-Sailfish_SDK_Target-i486.tar.bz2
# 更新 chroot
sudo ssu re 2.1.4.13
sudo zypper ref
sudo zypper dup
# 安装工具
sudo zypper in android-tools createrepo zip
未完待续 ?
May 10, 2018
WebAssembly StackOverflow
Mon Apr 30 16:50:47 2018
是一個設計運行在瀏覽器上的類彙編語言,
藉助它可以令 C / C++ 之類的語言運行在瀏覽器上,以期得到性能提升。
新功能自然會引入新攻擊面,可以預見 C / C++ 上經常出現的緩衝區溢出並不會在 WebAssembly 上消失。
有什麼不同
WebAssembly 同常見的彙編有很多不同的地方,例如
指令與數據隔離
因爲第三點,WebAssembly 在一定程度上是 ,這爲 WebAssembly 帶來了很大的安全優勢,但棧溢出仍是可能的。
我們舉個虛構的例子來證明 WebAssembly 棧溢出的可行性。
Rust 代碼:
[wasm_bindgen]
pub fn hash_with_key(key: &str, data: &str) -& u32 {
let mut val = [0; 32];
let key = key.as_bytes();
let data = data.as_bytes();
val[..3].copy_from_slice(&key[..3]);
val[3] = 0x33;
val[4..][..data.len()].copy_from_slice(&data);
js_hash(&val)
[wasm_bindgen]
pub fn table_index(i: usize) -& u8 {
let a = [b'a', b'd', b'c', b'b'];
unsafe { *a.get_unchecked(i) }
WebAssembly 的 wat 格式基於 ,指令精簡,與傳統彙編相比,相對容易閱讀。
但鑑於編譯出的 wasm 較長,下面我們只看我們關心的內容,
完整的內容可以看。
(global (;0;) (mut i32) (i32.const 1050544))
指令 global 定義了一塊可變的全局內存。
其中 1MB 是棧空間,剩下的是數據段。
(func $hash_with_key (type 2) (param i32 i32) (result i32)
(local i32 i32 i32)
get_global 0
i32.const 32
get_local 2
get_local 0
i32.load16_u align=1
i32.store16
get_local 2
get_local 0
i32.const 2
i32.load8_u
i32.store8 offset=2
函數 hash_with_key 在棧上開闢 32bytes,將 key 寫入棧上,而退棧時未將其清零。
(func $table_index (type 4) (param i32) (result i32)
(local i32)
get_global 0
i32.const 16
i32.const 12
get_local 0
i32.load8_u)
函數 table_index 在棧上開闢 16bytes,偏移 12bytes 讀取一個 byte。
簡單分析可以知道,在用戶正常調用 hash_with_key(..) 之後,
攻擊者只需要調用 table_index(16 - 12 - 32 + x) 便可獲得寫入棧上的 key。
雖然棧溢出是可行的,
但指令與數據的分離,使得我們只能讀寫棧內容而不能改變控制流。
這意味著 ROP、return2libc 之類的技巧不再有效,
棧溢出將只能在邏輯方面造成一些影響,危險度下降不止一個等級。
而 WebAssembly 想要支持 函數指針、虛函數、trait 對象,就必須引入一些動態方案。
WebAssembly 的方案是將所有需要動態使用的函數放入 ,
在運行時通過引索指定,並且在調用時會檢查函數簽名。
這個設計試圖在最大程度上降低風險,但無可避免的爲攻擊者開了一扇窗。
基於 WebAssembly 棧溢出,我做了一個簡單的 ,
源代碼託管在 。
有興趣的讀者可以一試。
本文有意忽略堆溢出,以避免引入衆多 Allocator 的複雜性。
作者不熟悉二進制安全、計算機原理。胡言亂語不知所云,有錯勿怪。
May 08, 2018
Windows 的
是可以生成
ss:// 的链接的,还可以生成二维码,于是不在本文的讨论范围内 (雾
一个普通的 Shadowsocks-libev 的配置文件大概长这样:
"server":"server_address",
"server_port":9999,
"local_address": "127.0.0.1",
"local_port":8888,
"password":"some_password",
"timeout":300,
"method":"aes-128-gcm",
在 Python 里可以用 json.read() 把 JSON 文件转换成一个字典:
# 偷点懒不单独写一行开文件啦……
import json
config = json.load(open("/path/to/config.json"))
一个普通的 ss:// 链接大概像这样
ss://{base64编码过的加密方式和密码,中间用冒号分开}@服务器:端口?插件;插件选项#配置名称
如果服务器是个 IPv6 地址,那么两边包上中括号……
对一个字符串直接 encode() 就有二进制流,反过来对着二进制流 decode() 就可以有字符串(感觉这说法好不正经 ?)
以及可以用 base64 模块对二进制流进行 base64 编码和解码:
import base64
encoded = base64.encodebytes("some_string".encode())
当然出来的也是个二进制流,需要的话可以再整成字符串,以及消除空白 ?
encoded_string = encoded.decode().strip()
其它的选项从配置文件里直接读就好,配置名称需要的话就写一个。
生成二维码
方法有很多 ? 例如用 pypi 里的 qrcode:
import qrcode
img = qrcode.make("some_text")
需要的话可以把这个图像保存到某个地方,然后打开它:
img.save("/path/to/images")
要在 Python 里运行其它程序?最简单的方法是 os.system() ? 稍微复杂一点的可以试试 Subprocess:
import subprocess
os.system("xdg-open /path/to/images")
subprocess.Call(["xdg-open","/path/to/images"])
这样就会用默认的图片查看器打开刚生成的二维码啦,用汝的手机扫一下看看? ?
水文 +1……
May 07, 2018
世界上有几百个还在更新的 Linux 发行版。新手常常感叹挑花了眼,换来换去也找不到自己满意的。维护一个发行版需要花费很多时间、精力,为何人们要这样“重复劳动”呢?
“强迫症患者”
我小时候追求整齐、秩序,无论是家里的电灯开关还是电脑上的图标,一定要排列的整整齐齐,不惜自己接电线、一个个重命名文件。“我的电脑”、“我的文档”、“网上邻居”,下面的蓝色 e 名字太长,就改叫“上网浏览”吧……然而随着安装了越来越多的软件,这些“秩序”被不断破坏,自己不断妥协。有的程序在我的文档里乱放目录——忍。有的程序会自动下载更新,然后在我代码写到一半的时候弹出来更新提示——忍。有的程序会带各种运行时包安装、替换系统文件导致另外一个程序运行不了——忍。
每次出了大问题的时候,所有人都告诉我:“现在只能重装了。”
2008年的时候,厌倦了折腾各种魔改定制 WinPE 的我首次下定决心安装了 Ubuntu 8.04,从此打开了新世界的大门。
不再需要依赖猜测。手握源代码,就如同掌握了施工的图纸,一切不符合心中秩序的地方都能找到原理。一群志同道合的前辈早已构建了井井有条的目录结构、依赖关系、软件仓库、……一切都显得那么美好。和每个第一次玩 Linux 桌面的折腾狂一样,我花了很多时间试图让 GTK+ 和 Qt 的程序界面一样而且好看,以及折腾 compiz 特效。
然而事情也不是那么完美。当时我在压片组用 x264 压片,采用的方案是使用加上一些特别 filter、并且带 lavf 输入的 x264 命令行。我用 wxPython 做了一些小工具,比如音轨提取、mkv 合成等,但是自动压片脚本需要的 x264 不能用仓库里的版本。我注册了 Launchpad 帐号并创建了一个 PPA,接下去,我花了很长很长时间都没有学会打出一个靠谱的包。别说各种 macro 的使用,就连拆包的部分都让我焦头烂额了。
长久以来折腾的零碎结果——各种经验、配置文件、补丁、翻译,散落在各种网站、论坛、聊天工具,而自己真正想分享出去的成果——软件包,又不知如何下手。我想要为这份秩序做点贡献,怎么办呢?后来群里的大牛们给我了一个简单一些的方法——AUR。
我在 2011 年安装了 Arch,从此找到了贡献之路。
使用 Ubuntu 的时候,我有过很多想打包的软件,也曾经用简单的 checkinstall 打出过数个“勉强算是包”的包,但是这个过程一直十分痛苦,以至于我搁置了大量的 TODO。
而在 AUR 里,一个简单的十几二十行普通 bash 语法的 PKGBUILD 文件,就描述完了一个包。字体、游戏、输入法,开发中用到的 python 库,都被我轻松地打成了 Arch 的软件包。2012 年,我申请成为了 Arch 的 Trusted User,将这些包中使用率高的部分加入了官方仓库。在 IRC 和 TU 们的闲聊中,我能感受到或多或少大家都是因为 pacman / PKGBUILD 体系的简洁、维护轻松而走到了一起。
一个人的力量是有限的,我很高兴我找到了这样一群和我类似的“强迫症患者”。开源软件千千万万,自己选择费心费力。有的作者很马虎,有的作者不喜欢条条框框,有的作者对安全更新嗤之以鼻——而发行版的打包者们,则成为了一道防线。我们形成了一些共识,无论是代码里的编译选项还是软件的默认行为,都会尽力向上游作者们争取、提供修改意见,或者直接提交补丁。这样的共识或许不完全和内心的秩序一致,但也已经相当接近了。每人维护一部分的软件包,承担起相应的责任,而其他人就可以坐享这份成果,大家的“强迫症”都得到了满足。
在我看来,这就是一个发行版存在的意义。轻易切换发行版使用的用户们,可能只是不像我们这么傻,这么认真。
近年来每每被问起诸如“Flatpak 会让发行版大一统”、“Docker 会让发行版大一统”、“把 npm 仓库里的包打成 Linux 软件包毫无意义”等等问题时,我时常会感到难以回答。不是没有道理可讲,实在是不知如何讲起。这些都是很有意义的理念和技术,只是它们取代不了形成一个发行版的共识。所谓共识,无非是在取舍时看重哪边更多一点。
Linux 发行版,作为基于共识形成的社区,正是由我这样的“强迫症患者”所组成。
May 05, 2018
由于 /usr/lib/libmozjs-52.so 的 SONAME 不符合其文件名, ldconfig 创建了未管理的文件 /usr/lib/libmozjs-52.so.0 。现在已经修正这一问题,两个文件都包含在新包中。
为防止更新报错,请于更新前删除 /usr/lib/libmozjs-52.so.0 。
April 30, 2018
下载 Windows JRE
获取32 位的 Windows JRE 压缩包,如 jre-8u172-windows-i586.tar.gz。这里使用压缩包是为了避免额外的安装步骤。
然后将 tar 包解压至 coolq 目录下,解压之后应该有 jre1.8.0_172/bin 等目录。
编辑 coolq/app/com.sobte.cqp.jcq/conf/setting.ini 文件,修改 JrePath 指定 JRE 路径(Docker 中的根目录对应 wine 中的 Z:\):
JrePath=Z:\home\user\coolq\jre1.8.0_172\
然后重启酷 Q,此时插件应该能找到 JRE。
参考论坛提供的 Demo 写插件。需要注意 json 文件中的 appid 字段,和 appInfo() 的返回格式。
然后编译构建,将 jar 包和 json 按正确的名称复制到 coolq/app/com.sobte.cqp.jcq/app/ 下,重启酷 Q 就会生效。
使用 maven-assembly-plugin 可以将依赖打进最终生成的 jar 包中。
stdout(竟然)是可用的,可以简单的使用 println() 输出调试信息。但输出的中文会乱码,原因是 Java 在 Windows 上的输出并不是 UTF-8 编码的。参考
修改 System.out 的编码后解决。
April 28, 2018
阿里云镜像制作踩坑记。
此文章主要记录按照 制作 VPC 镜像的过程。一些部分也可用作制作其他平台镜像的参考。
当然记录的原因主要是 Arch 上的 cloud-init 打死无法在阿里云上修改 root 密码,就很气。
建立虚拟机因为要制作 Customized Linux,所以第一步无法在阿里云平台上使用公共镜像制作。本机启动一个 Virtual Box,新建虚拟机,虚拟磁盘选择 RAW/IMG 格式即可。
按照一般步骤安装 Arch Linux,需要整个磁盘仅有一个分区。虽然很多平台支持多分区的镜像文件,但是莫名在这里踩了坑所以。
(另外吐槽:vps2arch 居然不帮我把 base-devel 装全了?!)
系统配置安装一些必需的包。
1# pacman -S qemu-guest-ga openssh
启用服务。
123# systemctl enable qemu-ga# systemctl enable sshd# systemctl enable systemd-networkd
网络配置哪个魂淡跟我讲 VPC 是 DHCP?装着 cloud-init 的 Arch 就可以自动设置内网 IP,这个没装的就 GG。
修改文件 /etc/systemd/network/default.network
12345[Match]Name=en*[Network]DHCP=ipv4
总之先这样放着。
定制脚本根据阿里云的文档,cloud init 不生效的时候需要用约定好的配置文件和脚本完成各种兼容动作。
新建目录 /aliyun_custom_image
新建文件 /usr/bin/aliyun-custom-os,写入内容
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485#!/bin/bashos_conf_dir=/aliyun_custom_imageos_conf_file=${os_conf_dir}/os.confload_os_conf() {
if [[ -f $os_conf_file ]]; then
. $os_conf_file
echo $password
fi}cleanup() {
rm $os_conf_file && /dev/null
mkdir -p $os_conf_dir}config_password() {
if [[ -n $password ]]; then
password=$(echo $password | base64 -d)
if [[ $? == 0 && -n $password ]]; then
echo "root:$password"
echo "root:$password" | chpasswd
fi}config_hostname() {
if [[ -n $hostname ]]; then
echo "$hostname" & /etc/hostname
hostnamectl set-hostname $hostname
fi}config_network() {
if [[ -n $eth0_ip_addr ]]; then
config_interface
systemctl restart systemd-networkd
fi}config_interface() {
mask2cdr $eth0_netmask
cat && EOF & /etc/systemd/network/default.network[Match]Name=$(ip link | awk -F: '$0 !~ "lo|vir|wl|^[^0-9]"{print $2a;getline}' | sed -e 's/^[[:space:]]*//')[Network]Address=$eth0_ip_addr/$netmaskGateway=$eth0_gateway[Link]MACAddress=$eth0_mac_address[Address]Address=$eth0_ip_addr/$netmaskEOF
echo "nameserver 1.1.1.1" & /etc/resolv.conf
for ns in $dns_nameserver
echo "nameserver $ns" && /etc/resolv.conf
done}mask2cdr() {
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%$3*}
netmask=$(( $2 + (${#x}/4) ))}if load_os_ then
config_password
config_hostname
config_network
cleanupelse
echo "not load $os_conf_file"fi
赋予执行权限
1# chmod +x /usr/bin/aliyun-custom-os
新建 systemd unit 文件 /usr/lib/systemd/system/aliyun-custom-os.service 写入内容
123456789101112[Unit]Description=Aliyun Custom OS Helper Script[Service]Type=oneshotExecStart=/usr/bin/aliyun-custom-osTimeoutSec=30StandardInput=ttyRemainAfterExit=yes[Install]WantedBy=multi-user.target
然后启用这个服务
1systemctl enable aliyun-custom-os
挂载镜像正常 shutdown 虚拟机,然后拿到镜像文件的路径。例如 ~/vm/archlinux.img。
接下来需要将此镜像挂载到宿主机系统中修改、清理文件。首先确定镜像文件中的分区位置:
12$ file ~/vm/archlinux.imgarchlinux.img: x86 partition 1: ID=0x83, active, starthead 32, startsector 2048,
sectors, code offset 0x63
得知 startsector 为 2048
123456789101112131415$ fdisk -l ~/vm/archlinux.imgYou must set cylinders.You can do this from the extra functions menu.Disk archlinux.img: 0 MB, 0 bytes255 heads, 63 sectors/track, 0 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x91d8e293
Device Boot
Systemarchlinux.img1
LinuxPartition 1 has different physical/logical endings:
phys=(1023, 254, 63) logical=(2610, 180, 2)
得知 sectorsize 为 512。
使用 mount 命令带 offset 参数挂载镜像中的分区:
12$ sudo mkdir -p /mnt/img$ sudo mount -t ext4 -o loop,offset=$((2048*512)) /path/to/archlinux.img /mnt/img/
就可以 cd /mnt/img 看到镜像里的 rootfs 啦。
清理/检查文件要删除的:
12345# rm /root/.bash_history # _(:з」∠)_# rm /etc/ssh/ssh_host_* # 强制每次部署的时候重新生成密钥对# rm -r /var/log/* # 清理不需要的日志# rm -r /var/cache/* # 清理缓存# rm /etc/resolv.conf.bak # 避免恢复成制作时的 DNS
要检查的:
/etc/hosts - 我不知道为什么,第一次的时候把这个文件留空了(:з」∠)
/etc/resolv.conf - 鉴于总是有人喜欢手动修改这个文件,所以直接把它写成静态文件好了。内容例如
12 8.8.8.8 8.8.4.4
/etc/ssh/sshd_config 中是否允许 root 密码登陆。
准备镜像退出 /mnt/img 目录,然后卸载镜像
1# umount /mnt/img
(可选)使用 qemu-img 转换镜像格式到 VHD,减少镜像文件大小。特别是对国内的小水管上传(心疼
1$ qemu- convert -f raw -O vpc archlinux.img archlinux.vhd
上传镜像在相同的 region 创建一个 OSS bucket,然后创建一个 RAM 子用户赋予 OSS 写权限并创建 Access Key,使用
上传准备好的 VHD 文件。
上传完毕后,在 ECS 标签下的镜像标签即可导入镜像。如果是第一次操作,需要给 ECS 授权访问 OSS。在导入的页面提示中提供了授权的链接。镜像内容配置如下:
OSS Object 地址:镜像文件在 OSS 中的 URL
Image 名称:archlinux-_64 … 等符合要求即可
操作系统:Linux
系统盘大小:40GB
系统架构:x86_64
系统平台:Customized Linux
镜像格式:VHD(如果是 img 就选 RAW)
镜像描述:随便写啦。
确定后应该就会开始制作镜像了。
测试因为没有做经典实例的兼容,这个镜像只能用于 VPC 的实例。总体而言,cloud-init 本来兼容的 Arch 却无法更改 root 密码(其他的倒是没问题),所以才选择了用一个 dirty 的方案来实现。
不知道应该说阿里云的工程师对自定义镜像的考虑周到还是对不同发行版的考虑欠妥…?
最后庆幸倒腾来去上传了好多遍 20G 的文件,日本运营商家宽带宽对等真的是帮了大忙,不然一个镜像制作不知道要到什么时候 & & (斜眼看国内三大运营商
阿里云镜像制作踩坑记。
此文章主要记录按照 制作 VPC 镜像的过程。一些部分也可用作制作其他平台镜像的参考。
当然记录的原因主要是 Arch 上的 cloud-init 打死无法在阿里云上修改 root 密码,就很气。
April 20, 2018
glibc 最新版本删除了 NIS 和 NIS+ 的相关支持。在 filesystem 包中默认的 /etc/nsswitch.conf 文件已经根据这一变化做了相应修改。请在升级前确认是否存在 pacnew 文件,并确保已经合并了其中的变更。
如果需要 NIS 功能,仍然能通过安装 libnss_nis 包提供该功能。不过对于 NIS+ 目前官方源中没有替代方案。
同时 pam 1.3.0-2 包不再提供 pam_unix2 模块以及 pam_unix_*.so 兼容性符号链接。请在升级前仔细检查 /etc/pam.d 文件夹中的 PAM 配置,用 pam_unix.so 替换掉以上被删除的模块。使用 pam_unix2 的用户还需要在修改 PAM 配置之后重置他们的密码。 pambase 包提供的默认配置不需要额外修正。
April 18, 2018
存储服务器不想放在 OVH 了。所以自己来托管一台机器,顺便折腾下 2x1Gbps 组 LACP Bonding。
前提:服务器需要至少 2 个千兆物理网卡,上联交换机支持 802.3ad。
配置交换机这里使用的是 Cisco Nexus 3064PQ-10GE 交换机,我们的接口在 Eth1/21-22,port-channel 的配置如下:
123456789# show interface trunk--------------------------------------------------------------------------------Port
Channel--------------------------------------------------------------------------------Eth1/21
Po100Eth1/22
Po100Po100
12345678910show port-channel databaseport-channel100
Last membership update is successful
2 ports in total, 2 ports up
First operational port is Ethernet1/21
Age of the port-channel is 0d:00h:02m:16s
Time since last bundle is 0d:00h:02m:04s
Last bundled member is Ethernet1/22
Ethernet1/21
[active ] [up] *
Ethernet1/22
[active ] [up]
配置服务器服务器操作系统是 Arch Linux,由于蜜汁问题 netctl 无法启动网卡,就只好用 systemd-networkd 啦。
麻烦一些,但是也还算顺利。与往常一样,折腾服务器网络的时候需要备着 IPMI 以防 connection lost。
内核模块需要加载 bonding 模块。将模块名写入列表,文件 /etc/modules-load.d/bonding.conf,内容只需要一行:
先别急着加载模块,为了防止模块自动建立一个默认网卡影响后续配置,以及设置 LACP Mode=4 … 等等,先加入一行参数。文件 /etc/modprobe.d/bonding.conf
1options bonding mode=4 miimon=100 max_bonds=0
然后安装 ifenslave 包,再 modprobe bonding 即可。
bonding 虚拟网卡首先创建一个虚拟网卡的设备。文件 /etc/systemd/network/bond0.netdev 内容为
123456789[NetDev]Name=bond0Kind=bond[Bond]Mode=802.3adTransmitHashPolicy=layer2+3LACPTransmitRate=fastAdSelect=bandwidth
然后在此虚拟网卡上创建网络。这里使用两个物理网卡 eth0 和 eth1 作为 bundle,交换机上的 VLAN id 是 113。文件 /etc/systemd/network/bond0.network 内容为
123456[Match]Name=bond0[Network]VLAN=vlan113BindCarrier=eth0 eth1
接下来分别为 eth0 和 eth1 建立网络设置。
/etc/systemd/network/eth0.network
12345[Match]Name=eth0[Network]Bond=bond0
/etc/systemd/network/eth1.network
12345[Match]Name=eth1[Network]Bond=bond0
最后是 VLAN 的设置。前面设置了上联 VLAN id 是 113,这里分别建立 VLAN 的虚拟网卡(based on bond0) 并设置网络(IP, etc)。
/etc/systemd/network/vlan113.netdev
123456[NetDev]Name=vlan113Kind=vlan[VLAN]Id=113
/etc/systemd/network/vlan113.network
12345678910111213141516171819[Match]Name=vlan113[Network]VLAN=vlan113[Address]Address=10.1.0.100/24[Route]Destination=0.0.0.0/0Gateway=10.1.0.1DNS=1.1.1.1[Address]Address=2600:x:x:x::2/64[Route]Gateway=2600:x:x:x::1
多个地址、IPv6 等可以写多个 [Address] 和 [Route]。
至此就完成啦。开启 systemd-networkd 的自启动:
1systemctl enable systemd-networkd.service
然后重启网络:
如果配置都没有问题,网络会中断十几秒然后恢复。现在查看网卡列表已经可以看到组合的网卡了:
1234567891011121314151: lo: &LOOPBACK,UP,LOWER_UP& mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:002: eth0: &BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP& mtu 1500 qdisc mq master bond0 state UP mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff3: eth1: &BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP& mtu 1500 qdisc mq master bond0 state UP mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff4: eth2: &BROADCAST,MULTICAST& mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff5: eno1: &BROADCAST,MULTICAST& mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff6: bond0: &BROADCAST,MULTICAST,MASTER,UP,LOWER_UP& mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff7: vlan113@bond0: &BROADCAST,MULTICAST,UP,LOWER_UP& mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether &REDACTED& brd ff:ff:ff:ff:ff:ff
ethtool 查看 bond0 的速率显示 2000Mb/s:
123456789101112131415161718Settings for bond0:
Supported ports: [ ]
Supported link modes:
Not reported
Supported pause frame use: No
Supports auto-negotiation: No
Supported FEC modes: Not reported
Advertised link modes:
Not reported
Advertised pause frame use: No
Advertised auto-negotiation: No
Advertised FEC modes: Not reported
Speed: 2000Mb/s
Duplex: Full
Port: Other
Transceiver: internal
Auto-negotiation: off
Link detected: yes
搞定收工(‘?ω?’)
Reference:
存储服务器不想放在 OVH 了。所以自己来托管一台机器,顺便折腾下 2x1Gbps 组 LACP Bonding。
April 16, 2018
可以从设置-网络-网络代理中设置:
(例如 wget 和 curl),会使用形如 "proto_proxy" 的环境变量用来设置代理啦
(当然也有可能是全部大写的),例如:
# export var=value
export http_proxy=http://10.203.0.1:5187/
export https_proxy=$http_proxy
export ftp_proxy=$http_proxy
export rsync_proxy=$http_proxy
export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com"
就设置成了 10.203.0.1:5187 作为 HTTP 代理,HTTPS、FTP 和 rsync 使用相同的代理。
于是可以把这样的语句写进一个脚本里在需要使用代理的时候 source 一下 ?
不过这样设置的环境变量一切换用户(例如 sudo)以后就没啦…… sudo 的话,可以用 -E 选项保持
环境变量,或者修改 /etc/sudoers 指定保持哪些环境变量:
Defaults env_keep += "http_proxy https_proxy ftp_proxy no_proxy"
curl 和 pacman 可以设置 all_proxy 变量直接使用:
export all_proxy="socks5://your.proxy:1080"
那剩下的怎么办 ?
字如其名就是个链式代理工具啦 ? Arch Linux 的话装上 proxychains-ng 就 OK 啦~
然后去修改 /etc/proxychains.conf ,选项有很多,
但是大多数时候只需要把最后一行换成汝自己的 socks5 代理的 IP 地址和端口就行?
然后就可以像平常(?)一样:
proxychains -q /path/to/program
有关 proxychains 的更多用法可以去参考它的文档:
Privoxy是一款不进行网页缓存且自带过滤功能的代理服务器,针对HTTP、HTTPS协议。
通过其过滤功能,用户可以保护隐私、对网页内容进行过滤、管理Cookie,以及拦阻各种广告等。
Privoxy可以单机使用,也可以应用到多用户的网络。
它也可以与其他代理相连(通常与Squid一起使用),更可以突破互联网审查。
同样 Arch Linux 上装上 privoxy 就 OK ?
然后去修改 /etc/privoxy/config ,选项还是有很多 ?,
但是大多数情况下只需要加上一行:
# forward-socks5
target_pattern
socks_proxy:port
http_proxy:port
# target_pattern 是 . 的话表示对所有域名适用
# http_proxy 是 . 的话表示继续不使用 HTTP 代理转发……
forward-socks5 . localhost:1080 .
然后启动 privoxy 服务,把 HTTP 代理设置成 localhost:8118 就好 ?
有关 Privoxy 的更多用法可以去参考它的文档:
April 15, 2018
Sun Apr 15 18:14:39 2018
是 redhat 放棄 Btrfs 之後推出的代替品,
使用類似 LVM 的方案來提供有如 btrfs、zfs 般強大的功能。
釋出 0.5 有一段時間了,今次抽出時間來嚐下鮮。
目前沒有面向用戶的文檔,故久違的寫一篇博文用以記錄。
從 AUR 安裝
然後啟動 stratisd
$ systemctl start stratisd
首先我們清理要用的塊設備
$ sudo wipefs -a /dev/sda
但當前版本創建 pool 的時候會碰到錯誤,stratisd 認爲這個塊設備已經被使用
$ stratis pool create stratis /dev/sda
Execution failed: 1: Device /dev/sda appears to belong to another application
如果塊設備的前 4/8k 字節未置零,stratisd 不會使用它。
知道原因就簡單了,我們將它置零
$ dd if=/dev/zero of=/dev/sda bs=1024 count=8
然後就可以正常創建 pool
$ stratis pool create stratis /dev/sda
$ stratis pool list
Total Physical Size
Total Physical Used
& 238.47 GiB
隨後創建 fs
$ stratis fs create stratis storage
$ stratis fs list stratis
$ la /dev/stratis/stratis/storage
Permissions Size User Date Modified Name
lrwxrwxrwx
9 root 15 4月
18:21 /dev/stratis/stratis/storage -& /dev/dm-6
創建完成,直接掛載就可以使用啦
$ sudo mount /dev/stratis/stratis/storage /run/media/quininer/storage
$ sudo chown quininer /run/media/quininer/storage
用得開心。 ;-)
April 09, 2018
貌似直接 dd 不起作用……
有人说 unetbootin 可行,但是咱装好以后一片空白…… ?
或者开个 Windows 虚拟机试试 rufus 或者巨硬的 Media Creation Tool ?(……)
于是就 ms-sys 了(不是 msys ?,是
首先把汝的 U 盘格式化成 MBR 分区表,然后新建一个 NTFS 分区并把它设置成活动分区 (cfdisk 一气呵成(误))
于是假设它是 /dev/sdb ,如果 mkfs.ntfs 的时候太慢的话可以加个 -Q 试试(
然后把 Windows 的安装 ISO 挂载上,里面的文件复制到 U 盘上。
把 Windows 7 的 MBR 写进 U 盘里去:
sudo ms-sys -7 /dev/sdb
把 NTFS 的 PBR 写进 U 盘的第一个分区(大概也是唯一一个)里去:
sudo ms-sys -n /dev/sdb1
大概就可以用啦 ? 于是咱又水了一次……
March 26, 2018
其实每个月都有不少人去世(参照 :讣闻 ),
不过听说霍金去和爱因斯坦谈笑风生(那天其实也是爱因斯坦诞辰)时还是有点震惊(误)。
虽然咱也就是翻过《时间简史》和《果壳中的宇宙》而已?
然后过几天看到了这个:
已确定在下午两点自杀并抢救失败(信息来源于她父母)
— 羽毛? (@zhangyubaka)
其实和这俩人不能算是太熟 ? ,不过在几天之前 @zhangyubaka 就一直在寻求帮助了,
还试图去找 @ayakaneko (虽然最后好像还是受到了威胁)。嘛现在就愿 Neko 安好吧~
有关事件的部分信息可以去看看某篇知乎专栏文章:
呜呜……说不出话来,只能说咱没经历过不太懂得受到的伤害 ?
从一个跟风总结开始 ?
/me 跟风来总结一下咱自己玩过的吧?现在经常玩的: IIDX,SDVX,Jubeat,maimai,Groove Coaster,Arcaea,Dynamix,Project DIVA Future Tone
现在在玩的;Cytus(1+2),OverRapid,Tone Sphere,Deemo,Superbeat XONIC,VOEZ
(未完待续)
— ホロ ? (@Ken_Ookami_Horo)
休闲了好几年…… ? 顺便给新的
打个广告 (划掉
感觉当初定下来的目标太大了的样子,又要 GNU/Linux ,还要兼顾一些隐私和安全保护相关
的知识……加上咱有没有那么多技能点……
曾经一度想用一个 GNU 钦定的 GNU/Linux 发行版(参见
最后还是放弃了,Debian 其实也海星 ?
嘛总之还是慢慢填吧……
March 22, 2018
Wiki 这么反人类的语法是怎么存在这么久的???????
总之受不了 Wiki 语法的可维护性了。什么?这玩意儿有维护性???
以及万年不更新的各种插件。系统升级后 PHP 7 不兼容,一看还是 swiftmail 的问题。生气。
正好有需求要整合一套知识库平台,搜索了一下 Confluence 的 alternative,发现了
前者适合个人或开源社区使用,后者则是一整套企业协作解决方案。对于我的需求来讲,BookStackApp 就足够啦。
页面数据DokuWiki 并不使用数据库,因此没有一个通用的中间件来实现数据格式转换。而 DokuWiki 的语法非常奇葩——比如,它的一级标题是 ====== 这样 ======,六级标题才是 = 这样 =,正好和一般的 Wikitext 倒置。图片、内链等的表达方式也相当愚蠢,这些问题使我在思考迁移方案的第一个小时内就放弃了直接从源码转移的途径。
顺便,还有另外一个问题——本来为了使 Wiki 易于编写,这 DokuWiki 还安装了 Markdown 插件。因此部分页面中混杂着 Markdown 语法,更增加了源码处理的复杂度。
综合来看,最通用的数据格式,就是最终渲染出来的 XHTML 了。
图片DokuWiki 的图片存储策略也是非常的奇特。由于它没有数据库,因此为了保持图片与页面的对应,它将图片存储在每个页面同样的路径下,并通过执行 PHP 的方式获取(扶额。
更甚者!!!
外链的图片,也是通过 /lib/exe/fetch.php 带参数来获取!!
因此既然在页面数据的考量中决定了使用最终渲染输出的 XHTML 来处理数据格式,图片也需要特殊的下载和归档技巧。这将需要使用 sanitize-html 提供的 transformer 方法来实现。
逻辑实现一开始尝试了一些 Site Exporter 插件,但遗憾的是并没有什么真正能派上用场。甚至一些暴力递归下载所有页面和资源的脚本的表现也非常糟糕。
但是根据 DokuWiki 的官方 Tips,它可以将文章内容单纯导出 XHTML,只需要加上 ?do=export_xhtmlbody 参数即可。这就方便了,因为这样只需要一个完整的页面列表就可以了。随便找一个可以输出子命名空间的插件,新建一个页面用于从根命名空间展开就 OK 啦。
请求这个列表页面的 XHTML body 输出,使用 cheerio 遍历所有的 a 标签,就获得了所有要导出的页面地址。分别再去请求这些页面的 XHTML body 输出,做如下处理:
跟踪所有的 img 标签,下载图片文件并按预定义的路径规则和文件名归档。
sanitize-html 清除所有不必要的标签、样式、id 和 class。
sanitize-html 按预定义的路径规则更新所有 a 和 img 标签属性。
后来发现 DokuWiki 的性能不足以支撑异步请求的速度,额外加上了 sleep 模块来控制请求频率(扶额。
脚本执行完后,将图片目录移动到 BookStackApp 的对应位置,便可以直接读取所有的 HTML 文件来导入数据啦。
用了这么久,才发现原来还有比 raw HTML 更难以维护的数据格式啊…(望天。Wiki 这么反人类的语法是怎么存在这么久的???????
February 23, 2018
zita-resampler 包的 1.6.0-1 版本在打包时缺失了一个库文件的符号链接,我们已经在 1.6.0-2 中加入了这个文件。如果您安装过 1.6.0-1 ,那么 ldconfig 将会在安装时创建这个链接,从而它会和 1.6.0-2 打包中的链接文件形成文件冲突。如果 pacman 提示文件冲突,请手动删除 /usr/lib/libzita-resampler.so.1 ,然后继续正常升级。
December 31, 2017
起因:Transifex 这货闭源一段时间后突然开始抢钱了。
正巧一堆开源项目需要一个在线协作的翻译平台,于是测试了几个比较知名的开源程序。一遍折腾下来,发现
可以最大化满足要求。顺便提一句,Weblate 也是有 hosted 付费服务的,但是在预算内的源字符串等限制依旧太多,所以选择使用他们的源码来搭建一套。
以及:我讨厌 Docker。
提供了非常全面的从起步到上手到各种高级用法的指南,因此这里不多赘述安装的过程。只记录少许踩过的坑。
这套程序看似简单,但实际上是基于 Django、使用了一大堆组件的复杂程序。如果想保持 system clean,最好(最快)的办法还是使用 Docker。
准备小型实例只需要一台虚拟机即可。但是即便只托管几个项目,它依旧会吃掉 2 个 CPU 核心和 4GB 内存,和曾经开源版的 Transifex 有得一拼 大概也解释了为何这类服务都死贵。
如果是托管在公网上的实例,则推荐使用 HTTPS。Weblate 的 Docker compose 提供了 HTTPS 支持,稍后会提到。
安装 Git, Docker 和 docker compose,在一些软件仓库中一般是 docker-ce 和 docker-compose,其他软件均不需要手动安装。
搭建首先克隆 docker compose 配置到本地
12git clone https://github.com/WeblateOrg/docker.git weblate-dockercd weblate-docker
为了直接开始使用 HTTPS,现在需要先建立域名解析记录,将要使用的域名(例如 weblate.example.com)指向服务器 IP。然后在该目录下创建配置文件 docker-compose-https.override.yml 内容如下
123456789101112131415161718192021version: '2'services:
environment:
- WEBLATE_DEBUG=0
- WEBLATE_EMAIL_HOST=smtp.gmail.com
- WEBLATE_EMAIL_HOST_USER=noreply@weblate.org
- WEBLATE_EMAIL_HOST_PASSWORD=system.email.password.here
- WEBLATE_ALLOWED_HOSTS=weblate.example.com
- WEBLATE_SERVER_EMAIL=noreply@weblate.org
- DEFAULT_FROM_EMAIL=noreply@weblate.org
- WEBLATE_REGISTRATION_OPEN=0
- WEBLATE_TIME_ZONE=UTC
- WEBLATE_OFFLOAD_INDEXING=1
- WEBLATE_REQUIRE_LOGIN=1
- WEBLATE_ADMIN_NAME=Weblate Admin
- WEBLATE_ADMIN_EMAIL=admin@weblate.org
- WEBLATE_ADMIN_PASSWORD=your+initial+password
https-portal:
environment:
DOMAINS: 'weblate.example.com -& http://weblate'
这份配置文件指定了:
关闭 Django DEBUG mode (即生产模式)
系统外发邮件服务器 smtp.gmail.com
系统外发邮件用户名 noreply@weblate.org
系统外发邮件密码 system.email.password.here
允许使用的域名 weblate.example.com,如果有多个域名,使用逗号隔开
系统外发邮件地址 noreply@weblate.org
关闭注册通道,用户必须管理员手动添加
设置系统时间为 UTC
打开后台索引,降低运行时的负载
执行任何操作前要求登陆
默认管理员名称是 Weblate Admin
默认管理员邮箱地址是 admin@weblate.org
默认管理员密码是 your+initial+password
然后在 https-portal 容器中指定了要使用 SSL 的域名 weblate.example.com 和后端指向的容器 http://weblate。
在当前目录中执行
1docker-compose -f docker-compose-https.yml -f docker-compose-https.override.yml up
会顺序拉取、启动 4 个 docker 容器,分别是:
https-portal
postgresql
第一次启动需要一些时间拉取镜像并导入初始数据。全部完成后,访问 weblate.example.com 应该可以看到一个 HTTPS 的 Weblate 实例运行,使用之前定义的默认管理员邮箱地址和密码即可登入。
此时转回终端,按一次 ^C 等待四个容器正确关闭,然后编辑 docker-compose-https.override.yml,删除以下配置
WEBLATE_ADMIN_NAME
WEBLATE_ADMIN_EMAIL
WEBLATE_ADMIN_PASSWORD
否则,如果更改了默认管理员的信息(如用户名等)下次启动会再次创建管理员帐号,并使用相同的邮箱,导致默认管理员无法使用邮箱登陆(报错返回 2 个用户信息)。解决办法是使用用户名…(摔
集成配置再次运行 docker-compose -f docker-compose-https.yml -f docker-compose-https.override.yml up 后可以很快启动所有需要的程序。此时登入 Weblate 实例,指向 /admin/ssh/ 点击创建 SSH 密钥。
在对单一 repo 提交的情况下,此 SSH Key 可作为 GitHub deploy key,但是如果需要多个不同 repo 提交时,有两种方法:
创建一个 GitHub 用户,然后将此 SSH Key 添加到此用户下,再给此用户所有必要的写权限
使用 Access Token 作为 HTTPS 密码访问必要的 repo
浏览器指向 /admin/trans/project/ 新建一个 Project。这个 Project 不仅指一个项目,也可以作为一个 Organization 的存在,更精确的解释是一个软件集,例如 KDE 套件可以包含一大堆的组件。
指向 /admin/trans/subproject/ 这里才是可以添加要翻译的项目的地方。如果对应的 repo 添加了公钥,这里可以直接使用 SSH 方式的 push URL。
File mask 填写所有语言文件相对 repo root 的路径,使用 * 代替语言代号。如果是 Monolingual language file,例如 key 是 user.info.comment_posted 这样而非原本即可阅读的文本,则 Monolingual base language file 和 Base file for new translations 均为源语言文件相对 repo root 的路径,这样即可正确识别源语言的字符串不至于让别人拿着 comment_posted 这样的 key 来猜意思
持续集成提交翻译后,Weblate 会在后台完成索引并提交必要的更改。当然也会一不小心刷了别人的屏…
在 repo 的 settings -& integration 中可以添加 Weblate 作为集成,每次有新的提交即可触发 Weblate 更新源语言文件。
结论我很开心可以。
当然,我依旧讨厌 Docker。起因:Transifex 这货闭源一段时间后突然开始抢钱了。
正巧一堆开源项目需要一个在线协作的翻译平台,于是测试了几个比较知名的开源程序。一遍折腾下来,发现
可以最大化满足要求。顺便提一句,Weblate 也是有 hosted 付费服务的,但是在预算内的源字符串等限制依旧太多,所以选择使用他们的源码来搭建一套。
以及:我讨厌 Docker。
December 30, 2017
今年写的文章只有去年的一半……看来摸了不少?啊?
搞了个 X230,自己刷上了 Coreboot 换上了新的无线网卡,装上了 Parabola( 似乎走上了一条不归路…… ?)
自己建的 Telegram 群全都解散啦?看来咱就是没有管理的能力啊……
突然从 FT 跳进了一个更大的坑,没错就是 NIMABE BEMANI ?
然后突然又和某个如梦方醒的学长一起学算法去了……
给别人安利音乐游戏然后自己被虐成渣…… ?
剩下的全忘啦?
其实有没有计划好像都没啥区别?
想考虑放个 PayPal 捐款链接上去(就是不知道哪里获取……)
或者像 uva 一样放个 coinhive js 上去(不过好像不少人讨厌的样子……)
不知道该写些啥……
不只要成为回忆而已~
(诶咱在说些啥)
December 18, 2017
突发奇想渲染 Minecraft 3D 效果图,首先用 Chunky 尝试了一下发现效果虽好但:
人物动作过于限制
渲染太!慢!了!
然而并买不起 Cinema 4D,所以来尝试一下 Blender 啦~
比较好的显卡。我的家用游戏机是 NVIDIA GTX 1080Ti,Cycles Render 可以 offload 掉绝大部分 CPU 的压力。
准备地图、材质、玩家皮肤等资源。
导出地图文件到 obj启动 jmc2obj,在最上方选择地图存档位置并单击 load。在 UI 里选择要导出的地图部分,点击 Export。在左侧的选项中依次:
Map Scale = 1.0
Center 选中,否则可能会出现在距离地图很远的地方
Texture Export
Pre-scale textures - 如果是原版材质,建议设置为 4x。如果是高清材质,按需要选择即可。
不勾选 Export alpha channel in separate file(s)
不勾选 Export all textures in a single file
选择从 Minecraft 安装里导出默认材质,或自行选择一个额外的材质包。
然后选择材质的导出位置。建议在目标目录中新建一个 textures 目录,然后导出到此目录中。此目录里面会出现一个 tex 目录,包含所有的材质文件。
材质导出进度完成后,开始导出地图文件。在右侧的选项中依次:
取消所有的选项勾选
勾选 Create a separate object for each material
可选勾选:
Render Entities
Occulude different adjacent materials
Optimize mesh
Do not allow duplicate vertexes
其余选项均保持非勾选状态
点击 Export 导出到之前创建的 textures 的 同级目录
可能会遇到 banner 找不到材质的问题,忽略继续。导出后还不能使用,需要一个简单而 ugly 的 hack - 再导出一遍覆盖之前的 obj 和 mtl 文件。
导出后的工作目录如下:
.obj 文件是地图数据,.mtl 则是刚才导出材质的材质索引,指向 textures/tex 的相对路径,因此这些文件的相对位置不能改变。
安装 MCPrep启动 Blender,在 File -& User Preferences -& Add-ons 里,选择 Install A}

我要回帖

更多关于 宝石星球密码缺少参数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信