What have you found for these years?

Showing posts with label 筆記. Show all posts
Showing posts with label 筆記. Show all posts

2018-10-11

Multiple inboxes in GMail

Now I am trying very hard to fight with my exploded inbox,
and I found that multiple inboxes from the advanced features
in GMail somehow works. The UX is not smooth enough, because
it's not refreshing the unread status fast enough, but at least
this is something.

Enable multiple inboxes:



And here's my setup:



Basically:

0. Important unread emails
1. Regular unread non-GitLab emails
2. Unread GitLab emails beside the GitLab Bot
3. Unread GitLab emails from the GitLab Bot

I am still flooded with responses from the threads the Bot had added comments,
but I'll see how this will work out in tomorrow's batch.

2018-07-06

Let's Encrypt for *.godfat.org

This is a note to myself so that if my server breaks I could easier recover it.

* Use dehydrated (renamed from letsencrypt.sh)
* Use letsencrypt-manual-hook
* Set domains.txt as godfat.org *.godfat.org > godfat.org
* Run: ./dehydrated --cron --challenge dns-01 --hook 'hooks/manual/manual_hook.rb'
* Go to my DNS provider and setup TXT records manually. Twice Two TXT records in the same time.
* sudo cp certs/godfat.org/fullchain.pem /etc/nginx/ssl.crt
* sudo cp certs/godfat.org/privkey.pem /etc/nginx/ssl.key
* sudo systemctl restart nginx

2018-03-16

Backup Google Authenticator secrets

So I finally rooted my new Pixel 2, transferring over my data,
game saves, and setting up everything including Google Authenticator.
Now the most important step! The very reason why I want to root
my Android, to backup Google Authenticator secrets...

What an awful idea to make it only able to backup with a rooted device.

Here are the steps:

# Enable Developer options on the phone
# Enable USB debugging

# Connect the phone with the computer
$ /usr/local/share/android-sdk/platform-tools/adb shell

walleye:/ $ su
# Grant superuser privilege from the phone screen
# If it's not popping up, and it shows permission denied,
# then go to Magisk app which we used to root, and find
# the option to grant superuser privilege to Shell manually
walleye:/ # cp /data/data/com.google.android.apps.authenticator2/databases/databases /sdcard/Download

# Ctrl-D to leave phone console

$ /usr/local/share/android-sdk/platform-tools/adb pull /sdcard/Download/databases .
$ sqlite3 databases
sqlite> select * from accounts;

# You should see all your secrets!

Of course, remove /sdcard/Download/databases on the phone afterward.
Keep that sqlite3 database in a safe place. (or just copy the secrets and remove it)

References:

* Manually Extract Your Credentials [Root Only]

2018-03-15

Rooting Pixel 2 with MacBook

# Install tools on the computer
$ brew cask install android-sdk
# Install platform-tools in order to have adb
$ sdkmanager platform-tools

# Download official Android image:
# https://developers.google.com/android/images
# Extract everything and find "boot.img"

# Download Magisk (the only 3rd party stuff)
# https://www.apkmirror.com/apk/topjohnwu/magisk-manager/

# Enable Developer options on the phone
# Enable OEM unlocking
# Enable USB debugging

# Connect the phone with the computer

# Check if connected
$ /usr/local/share/android-sdk/platform-tools/adb devices

# Boot to bootloader
$ /usr/local/share/android-sdk/platform-tools/adb reboot bootloader

# Check if fastboot is available
$ /usr/local/share/android-sdk/platform-tools/fastboot devices

# Unlock the bootloader (NOTE: This would WIPE all the data)
# Run it only after backing up
$ /usr/local/share/android-sdk/platform-tools/fastboot flashing unlock

# UNLOCK THE BOOTLOADER

# Reboot the phone
$ /usr/local/share/android-sdk/platform-tools/fastboot reboot

# Setup the phone again
# Enable Developer options on the phone again

# Upload Magisk and "boot.img" to the phone
$ /usr/local/share/android-sdk/platform-tools/adb push 'magisk_5.6.2.apk' /sdcard/Download
$ /usr/local/share/android-sdk/platform-tools/adb push 'boot.img' /sdcard/Download

# Install Magisk from Downloads
# Click "Install", "Patch Boot Image File" and pick "boot.img" from Downloads

# Download the patched_boot.img from the phone to the computer
$ /usr/local/share/android-sdk/platform-tools/adb pull /sdcard/MagiskManager/patched_boot.img

# Reboot to bootloader again
$ /usr/local/share/android-sdk/platform-tools/adb reboot bootloader

# Flash the patched image
$ /usr/local/share/android-sdk/platform-tools/fastboot flash boot patched_boot.img

# Reboot
$ /usr/local/share/android-sdk/platform-tools/fastboot reboot

# All done!

References:

* How to root the Google Pixel 2
* [GUIDE] Unlock/Flash/Root for the Pixel 2 (walleye)

2016-02-25

Finally got letsencrypt done

Finally got letsencrypt done.

I don't quite understand why the official scripts were so complicated,
but finally I got it done with letsencrypt.sh (Thanks Ash for
recommending it) along with some scripts from letsencrypt-nosudo.

This is a note for what I've done in case I need to do this again.
First let's clone it first:

git clone git@github.com:lukas2511/letsencrypt.sh.git
cd letsencrypt.sh

Then let's generate a private key and a signing request:
(This was from letsencrypt-nosudo)
openssl genrsa 4096 > domain.key
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) > domain.csr
Note that the second command cannot run under Fish,
and I would like to know if there's any way to create a wildcard certificate?
I tried to use *.godfat.org however it seems letencrypt doesn't allow it.

Let's setup the other configs:
echo example.com www.example.com > domains.txt
mkdir .acme-challenges

Finally setup Nginx for acme-challenge:
(Note that letsencrypt.sh would write files into it and clear it after done)
# /etc/nginx/nginx.conf
location /.well-known/acme-challenge {
  alias /home/example/letsencrypt.sh/.acme-challenges;
}

Begin hitting letencrypt:
./letsencrypt.sh --signcsr domain.csr

You'll get the certificate printed on stdout. Not sure if there's a way to
output it to a file, but anyway you could just copy it and put it in a file.
I'll assume you put it in domain.crt and we could continue
setting up Nginx:
mkdir dist
# Download the other certificate from letsencrypt (source)
wget https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem
# Bundle it for the final certificate:
cat domain.crt lets-encrypt-x1-cross-signed.pem > dist/ssl.crt
# Setting up the final files
cp domain.key dist/ssl.key
chmod 600 dist/ssl.key
chmod 644 dist/ssl.crt
sudo chown root:root dist/ssl.*
sudo cp dist/ssl.* /etc/nginx/

And here's the relevant Nginx config:
# /etc/nginx/nginx.conf
server {
  listen 80;
  listen 443 ssl http2;
  ssl_certificate ssl.crt;
  ssl_certificate_key ssl.key;
  ssl_session_timeout 5m;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1.2;
  ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
}

After restarting Nginx, you could verify it with ssltest.

P.S. Thanks to StartSSL started involving something with China
pushing me forward this. I was so lazy figuring out how it works
before. The world deserves free/cheap secure connections for
independent developers/organizations.

2016-02-16

Whenever Sublime Text updates...

I'll need to do:

cd '/Applications/Sublime Text 3.app/Contents/MacOS/Packages'
ln -s Ruby.sublime-package Ruby.sublime-package.zip
# Find:
# Snippets/require-..-(req).sublime-snippet
# Change " to '

# Find:
# Ruby.sublime-syntax
# Search:
# require
# Remove `push:` clause

ln -s 'Color Scheme - Default.sublime-package' 'Color Scheme - Default.sublime-package.zip'
# Find:
# Twilight.tmTheme
# Add color scheme for GitGutter
# Add just before <plist><dict></array>
# Change color:
# deleted -> #FF0000
# inserted -> #00FF00
# changed -> #FFFF00

ln -s 'Default.sublime-package' 'Default.sublime-package.zip'
# Find:
# block.py
# Find:
# def indented_block(view, r):
# Insert:
#         return False
# To avoid inserting } in the wrong block

2014-12-29

fish like up/down history search for readline (or bash)

I am not sure if everyone already knows this,
but I just hardly found this on the Internet.
Seriously, this should really be the default!

finally!! fish like up/down arrow for readline!

Here's the .inputrc you would use:

"\e[A": history-substring-search-backward
"\e[B": history-substring-search-forward

I don't care about bash because I am using fish,
but for things like rib or other interactive shells
are all using readline. This should give them
the power of full-text search for history.

Fish still did a better job to highlight the matched
text, but it's probably good enough for now.

2014-08-10

edit last git commit

git reset --mixed HEAD~1
git commit -c ORIG_HEAD

2014-02-17

Rails + Bower on Heroku

Tested with Rails 3.2.15 and Bower 1.2.8.

First we need both Heroku's NodeJS and Ruby buildpacks,
using a multi-buildpack which could combine buildpacks.
Run this command to enable this multi-buildpack:

heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

Then we need to create a .buildpacks file to
specify which buildpacks we want to use.

$ cat .buildpacks
https://github.com/heroku/heroku-buildpack-nodejs
https://github.com/heroku/heroku-buildpack-ruby

Next, we need a package.json for Heroku to
install npm dependencies, and run bower install.

$ cat package.json
{
  "name": "example",
  "version": "0.0.1",
  "repository": {
    "type": "git"
  },
  "dependencies": {
    "bower": "*"
  },
  "engines": {
    "node": "0.10.x"
  },
  "scripts": {
    "postinstall": "./node_modules/bower/bin/bower install"
  }
}

Note that repository is for silencing warnings from npm,
and scripts is where we specify how to run bower install.

Here's the bower.json to specify dependencies:
$ cat bower.json
{
  "name": "example",
  "version": "0.0.1",
  "dependencies": {
    "normalize-css": "*",
  },
}

We also need to specify the installation path for bower:
$ cat .bowerrc
{
  "directory": "app/assets/components"
}

We tried to install to this path because it seems Rails is
aware of this path, and people are using it. (Honestly, I don't
yet really understand what's Bower doing, just want to make it work)

Hopefully the last one, telling Rails to precompile assets from Bower.
We need to put this into our config/application.rb:
# Precompile assets from Bower
prefix = "#{Rails.root}/app/assets/components"
config.assets.precompile.push(*Dir["#{prefix}/*"].map{ |path|
  "#{path[/^#{Regexp.escape(prefix)}\/(.*)/, 1]}/*"
})

Updated 2014-08-12 00:04
This might work better:
config.assets.precompile = [lambda do |path|
  !path.start_with?('jquery/src') &&  # exclude broken jquery
    %w[.js .css .svg .png .jpg .gif .ttf .woff .eot .wav .mp3 .ogg].
      include?(File.extname(path)) && # compile only them
    Dir['app/assets/*'].find do |base|
      File.exist?("#{base}/#{path}")  # compile only from app/assets
    end
end]

I don't really understand why we need to do this, but I guess
this is how Rails designed, and I am too tired to argue with this.

That's basically everything we made Rails and Bower work on Heroku.

Example logs from Heroku:
-----> Fetching custom git buildpack... done
-----> Multipack app detected
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs
=====> Detected Framework: Node.js
-----> Requested node range:  0.10.x
-----> Resolved node version: 0.10.25
-----> Downloading and installing node
-----> Restoring node_modules directory from cache
-----> Pruning cached dependencies not specified in package.json
-----> Exporting config vars to environment
-----> Installing dependencies

       > example@0.0.1 postinstall /tmp/build_random-uuid
       > ./node_modules/bower/bin/bower install
[...]
-----> Caching node_modules directory for future builds
-----> Cleaning up node-gyp and npm artifacts
-----> Building runtime environment
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby
=====> Detected Framework: Ruby
-----> Compiling Ruby/Rails
-----> Using Ruby version: ruby-2.1.0
-----> Installing dependencies using 1.5.2
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
[...]
       Your bundle is complete!
       Gems in the groups development and test were not installed.
       It was installed into ./vendor/bundle
       Bundle completed (1.29s)
       Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
[...]
-----> WARNINGS:
       Injecting plugin 'rails_log_stdout'
       Injecting plugin 'rails3_serve_static_assets'
       Add 'rails_12factor' gem to your Gemfile to skip plugin injection
       Using release configuration from last framework Ruby:
       ---
       addons:
       - heroku-postgresql:dev
       default_process_types:
         rake: bundle exec rake
         console: bundle exec rails console
         web: bundle exec rails server -p $PORT
         worker: bundle exec rake jobs:work
-----> Discovering process types
       Procfile declares types     -> web, worker
       Default types for Multipack -> console, rake

-----> Compressing... done, 12.93MB
-----> Launching... done, v1293
-----> Deploy hooks scheduled, check output in your logs
       http://example.herokuapp.com deployed to Heroku

To git@heroku.com:example.git
   fee1dead...deadbeef master -> master

2013-12-10

tracing in pow

I wondered what's happening in pow, so I tried to trace
what it is doing. My conclusion is, how could this be
even more wrong?

Please follow me to see what's happening...

So on it's website, it's telling the users to install it via:

curl get.pow.cx | sh
Aside from the point that you should never do this (please
download the shell script and take a look before running it),
it is basically install.sh, which is trying to download a
tarball
for the specific version of pow and untar it,
and run the pow command to install the whole thing.

It would do a number of things. Let's only look at the
important ones, or there would be too much to look at.

So the pow command would pick the system installer,
it would then install a firewall plist, a number of
resolver configs, and a plist for pow itself in its
local installer.

After that, the installer would load the firewall with sudo,
and start pow via pow plist.

Note that since they are doing this in /Library/LaunchAgents
and /Library/LaunchDaemons, they would be running when
Mac OSX starts.

*

And what are they doing? There are a number of files
we should be looking at. Let's go through them one by one.

The firewall is probably cx.pow.firewall.plist.eco.
It is trying to forward port 80 to port 20559 by default.
That means, whenever you're hitting http://pow.dev:80 it
would be forwarded to http://127.0.0.1:20559.

Let's look into the DNS resolver, which I believe it's
resolver.eco, which would be installed into
/etc/resolver/dev with sudo.

According to Mac's resolver man page, this means only
domains ending with dev (or whatever it's configured) would
use this pow DNS server, listening on 20560 by default.

Lastly, the pow plist itself, which I think is cx.pow.powd.plist.eco,
which is simply trying to launch Node to run pow command.

*

So by installing pow, it would then install a pow daemon,
which itself is both a DNS server and an HTTP server. We'll
talk about this later. It would also install a special DNS
resolver for domains ending with .dev, and a firewall rule
for forwarding port 80 to port 20559.

In the end, what does pow really do for serving a request?

Mac would first look at /etc/resolver/dev and realize that
it needs a special DNS server located on 127.0.0.1:20560,
which is a pow DNS server, resolving the IP of the domain to
127.0.0.1, and the browser would then try to make a request
against 127.0.0.1:80, with header Host: whatever.dev, which
then the firewall would forward the request from 127.0.0.1:80
to 127.0.0.1:20559, which is the pow HTTP server, which would
try to look at ~/.pow/whatever, locating the config.ru, spawning
a nack_worker process, which is a Ruby server, listening on a
UNIX domain socket, and in the mean time, converting the request
object into a netstring embedding a JSON, writing into the UNIX
domain socket, and the nack_worker would parse the netstring,
extracting the JSON, parsing the JSON, and builds the Rack env
object based on the JSON it reads, finally calling the Rack app,
passing the response back to pow, and back to the browser.

Oh wait, it might not really pass the request along to the Rack app.
It could be intercepted by pow if the requested path matches a file
located in the particular Rack app's public directory.

Seriously? Sorry that I am too lazy to link the source line by line.
This is simply too much. It also needs to handle RVM stuffs, yet
another pile of stuffs.

I would much prefer a simple command to launch a server.
If you're developing a number of applications, and need to run them
at the same time, then I believe you must have the ability to solve
this in a more elegant way.

Maybe write a pow equivalent in Ruby, then all the conversions
could be omitted. We could simply spawn Ruby processes. I don't
see what's the point of using Node to run Ruby.

2012-11-23

iTerm2 colors: Dark Illumina

DarkIllumina.itermcolors
License: MIT




Palette: Web Safe Colors

Foreground:    #CCC
Background:    #000
Bold:          #6CF
Selection:     #666
Selected Text: #000
Cursor:        #FFF
Cursor Text:   #000

Black:   #333 Bright: #666
Red:     #C00 Bright: #F00
Green:   #090 Bright: #0F0
Yellow:  #CC0 Bright: #FF0
Blue:    #36F Bright: #09F
Magenta: #C3F Bright: #F0F
Cyan:    #0CF Bright: #0FF
White:   #CCC Bright: #FFF

2012-11-22

資料轉移步驟 (2) 調教

嘿嘿,我居然真的成功把 scrolling 調回正常了!!
果然只要有心 google, 還是可以解決呀(泣)

雖然步驟真的很多,要改三樣東西。

首先是:
Disable elastic scrolling in OS X
跑這個

defaults write -g NSScrollViewRubberbanding -bool false
接著是:
Disable smooth scrolling in Mountain Lion
跑這個
defaults write -g NSScrollAnimationEnabled -bool NO
最後是:
Disable Inertia Scrolling in Mac OS X Lion
不是跑指令,是去 Accessibility 裡的 Mouse & Keyboard 的 Trackpad Options 選:
Scrolling without inertia
就可以像以前一樣用比較有效率的方式捲動畫面了...

真是喘口氣呀。接下來還有一狗票要改的,例如這個:
Disable Auto-Save and Versions in Mac OS X
不過我還沒仔細研究,看起來是要每個程式都跑一次才行。
defaults write com.apple.Preview ApplePersistence -bool no
defaults write com.apple.TextEdit AutosavingDelay -int 0
好像是可以用 defaults domains 調查有哪些需要改吧?然後說不定也要用:
Turn Off File Locking in OS X Lion
還不確定要怎麼弄,就先筆記起來這樣。

另外是三指滑動卷到頭和尾居然沒用了。這篇說要額外灌軟體才能解決了 :(
How to get the three finger 'scroll to top' back in mountain lion?
另外記得要在 Trackpad 裡面把 mission control 和
app expose 關掉,因為那兩個佔用了三指滑動.. 居然改掉這麼好用的功能,不知道該說啥。

另外還有注意到如果 dmg 正被 mount 住的話,不能移除那個 dmg 檔,變得比較像 windows.
不確定這是好事或是壞事,好處是比較不會誤刪,壞處是有時候我真的要刪呀,這樣很討厭,
dialog 裡面應該要允許我強制刪除的。不過反正我用 rm 也行,就罷了。

再來是希望能把字體改大一點,感覺 10.8 字體又變更小了,閱讀得好吃力呀.... :(
或是因為我之前在 10.6 時用 TinkerTool 把某些字體改大了,所以才覺得還勉強?
總之雖然不抱什麼希望,還是希望能改大。

另一個改掉的是 Keyboard 裡把 ctrl+左 ctrl+右 的熱鍵拿掉。那個應該要留給 terminal 用。
我覺得 mac 用 terminal 其實有個好處,就是系統的熱鍵全部是 cmd+ 而 ctrl+ 可以保留給
terminal 裡面的 application 用。例如複製貼上可以用 cmd+c 和 cmd+v, 而不是用奇怪的
shift+insert 還什麼的。ctrl+c 仍然是 interrupt, 這樣很好。

還有無盡的設定要弄,不過目前看起來很順利,第三天應該可以弄完...。
啊不過這些我應該慢慢弄的,現在比較急切的應該是把檔案移好位置,不需要的刪除,
然後趕快建立 TimeMachine 做備份才對。微調這種事雖然很容易讓我陷進去,但還是最後弄比較好。

2012-11-21

資料轉移步驟

拿到新電腦了,不過看來轉移工程相當巨大... 會慢慢更新進度。

(o) 用很老舊的(不知道有沒有十年) DVD+RW 燒錄 Mac OS 10.8 安裝光碟
(o) 用安裝光碟開機,重新格式化硬碟為 HFS+ case sensitive (對,我學不乖 :P)
(o) 改回英文語系並重新安裝
(o) 調回正常的 scrolling 方向與其他基本的設定
(o) 更新 OS
(o) 安裝 Firefox (對我來說 Safari 跟 IE 似乎沒啥兩樣)
(o) 安裝 Asepsis 避免可惡的 .DS_Store

新電腦處理暫時到這,接下來移轉資料再調整其餘設定。

(o) sudo chown -R godfat:staff /Users/sftp
(o) 將 /Users (600G) 複製至 external Seagate 2T HDD, 其中一顆 TimeMachine
(o) 確認複製內容是否正確(很難確認,不過還是要稍微確認一下)
(o) 將 /Applications 複製至同上硬碟
(o) 看看 /usr/local 有什麼需要複製的
(o) 想想 /Library 之類的有沒有需要複製的

回到新電腦。

(o) 將以上所有資料複製進新電腦的硬碟 750G 7200rpm
(o) 安裝 Command Line Tools for Xcode
(o) 安裝 Homebrew
(o) 安裝 Ruby, Git, Haskell-Platform 等等,參考原本電腦裡有裝啥
(-) 將複製來的資料整理一下,例如 ~/Pictures 可以放 archive, 但 ~/project 是要用的
(-) 看看原本 /Applications 有什麼是需要放回去的,並視情況複製 ~/Library/Application\ Support
(o) 刪除用不到的 applications, 例如舊的 Terminal 當然不用了

下一階段。

(o) 把之前 WD 1.5T 拿出來重新格式化 HFS+ case sensitive 做新電腦的 TimeMachine
(o) 考慮 Samsung 1.5T 和 Seagate 2T 要怎麼處理,要做新電腦 TimeMachine 嗎?
(o) 或是再買一顆做新電腦 TimeMachine, 之前那兩顆先當 archive
(-) 封存原本電腦,看看有沒有人有興趣?同時有一顆 500G 可以替換我原本的 680G

最後階段。

(o) 重新安裝一些我需要用到的軟體,例如 Total Finder, iTerm, 中文輸入法之類的
(o) 調整其他重要的設定,例如讓 Finder 顯示隱藏檔案,並調查還有啥隱藏設定可設
(o) 看看 scrolling 到邊緣會跳動的問題到底可否解決
(*) 安裝各種 Firefox addons, 把原本 Greasemonkey 裡的資料複製進來
(-) 想想看一百多個 Firefox tabs 要怎麼在新 Firefox 重現..... 手打!?
(o) 研究一下新功能,例如我還搞不清楚 Mission Control 是啥鬼東西
(x) 建立 sftp 與公司帳號,希望以前寫的 useradd-mac 還能用。

我現在都盡量保留原本的硬碟當 version history archive...
原本備份的一堆 CD 和 DVD 也都還在,雖然目前為止是沒有回頭去打撈什麼。
另外之所以不用 TimeMachine 的 copy, 而要再 copy 一次是因為之前發現
TimeMachine 很詭異的有些東西沒有備份到。所以為了保險起見,這次整個重來。

到這裡,我回頭去用 Windows 的機率不高了。一方面是既然有新 MacBook Pro 了,
沒有太多理由再換 Windows. 另一方面是我發現 Windows 還是有不少地方讓我
很不滿意,而且有一些是真的問過很多人還是沒辦法改善的。當然有些最後應該可以接受,
但調整過程應該會很漫長,想到就覺得很麻煩。因此就下次要再換電腦時再說吧 :o

反正就做好隨時跳船的心理準備就好了 XD

2012-11-12

最近奇妙的睡眠狀況

其實我記得不是很清楚了,仔細想想我應該記錄一下看看的,
因為我想知道我的一天是否真如預測般是在 25~29 小時間 XD

回憶起來大概類似這樣...

睡 09:00 ~ 20:00 (睡 11:00) 週二 25:00
醒 20:00 ~ 10:00 (醒 14:00)
睡 10:00 ~ 21:00 (睡 11:00) 週三 43:30 (snap 03:00)
醒 21:00 ~ 05:30 (醒 32:30)
睡 05:30 ~ 11:30 (睡 06:00) 週五 24:30
醒 11:30 ~ 06:00 (醒 18:30)
睡 06:00 ~ 21:30 (睡 15:30) 週六 38:00
醒 21:30 ~ 20:00 (醒 22:30)
睡 20:00 ~ 03:30 (睡 07:30) 週一 ??

我一開始寫成週二到週日,但把長度算出來後就覺得不太對,
數字那麼多,加起來早就超過正常的天數了... 後來才意會到
我週四沒有睡,所以不應該寫出來的,應該算是被吃掉的一天...

這週大概就是日夜顛倒的一週,然後在週四時打算不睡,
這樣才有可能在白天醒著到辦公室。不過那天又弄到半夜,
整個感覺就是累到要死。現在總有種幹嘛這麼拚的感覺...

週五為了在白天起來,也只睡了一點點的六小時,平常的一半多。
後來去了煙霧瀰漫的地方,又喝了一點酒,覺得很累,後來頭也很痛。
說是這樣說,我還是混到早上六點才睡,因為頭實在太痛了。
至於為什麼老要混到那時候才睡,因為我睡前一定要一點自己
打電腦的時間(通常是數小時...),不這樣做無法安心睡覺。

也因為太累了,週六就一口氣睡了十五個半小時 @_@
這個數字就算對我而言,也是比平常多不少。平常我最多大概
就睡到十二個小時,不容易更多了。

接著就是 guildwar2 打到瘋掉... 連續打超過十二個小時 @_@
不知道該說好爽還是有種總算出一口怨氣的感覺..??

不過很詭異的是,我晚上八點左右開始睡,睡到十二點就醒來了。
那時候就不是很想睡,感覺還滿有精神的。但是我知道這樣睡太少了,
而且爬起來的話又會日夜顛倒得很嚴重,所以就強迫繼續睡。

接著就被隔壁的吵得要命,害我忍不住大吼大叫,不知道他們
聽不聽得到。我猜他們不夠敏感,又一直在講話的話大概聽不到。
我也是安靜的時候才會覺得很明顯,講話時只是隱隱約約有聲音而已。
我還夢到對隔壁大吼,然後隔壁吼回來... 我覺得應該是夢吧,
因為醒來當下我並沒有真的吼出去的印象...

我電風扇都已經開第二級了,還要被他們吵實在是很煩。開更大的話,
我反而就會開始覺得電風扇吵了 :( 二級就已經很大聲了說,
連冰箱的噪音都不明顯了。如果沒開電扇的話,我想我會被冰箱吵醒,
結果這次開電扇還是被隔壁吵醒。

不過其實這也表示著我並沒有那麼想睡是真的。這也是為什麼我睡到
三點半後,覺得已經到了極限,決定爬起來了。雖然我僅僅睡了七個半。

我依然認真覺得,睡眠時間其實取決於我的心情狀態。不是很好的時候,
睡眠時間大約需要 10~12 小時,而且通常是爬不起來,要滾很久很久
才有辦法不甘願地起床。最好的情況的時候,平均睡眠只需要 7~9 小時,
而且是真的會想爬起來,不是不甘不願地!後者其實是重點。
這次睡七個半小時差不多就是這個狀況了。

不過我是打定主意要再打一下 guildwars2 的,哈哈哈哈哈哈哈。
上一次沒有不甘願地起床是幾時?多麼難得呀,要好好品嘗一下 (?)

(終)

話說我現在想想,也應該紀錄吃飯時間的。不知道有沒有什麼好工具可以
紀錄吃飯和睡覺的時間?單用記憶太不可靠了,而且硬要回想好累。
把這些數字和當下感覺都記錄下來,應該可以找到一些規則才對。

每次想到這裡就會想到 American McGee's Alice 的那本小冊子。


p.s. google 還滿蠢的,查 American McGee's Alice 會問:
Did you mean: America McGee's Alice
顯示第一筆則是正確的 wikipedia 的 American McGee's Alice
按下這個錯誤的建議後,出來的還是一樣是 wikipedia, 然後再問:
Did you mean: American McGee's Alice
啊是你剛剛自己建議我錯誤的搜尋字,現在後悔了?

所以總之 Did you mean 也是有 mutual recursion 的...

2012-03-07

spellbook 紙牌版 quick note (0)

posted on g+
spellbook 紙牌版 quick note

稍微想了一下 spellbook 紙牌版...

分三個部分
0. 組卡 card composing
1. 組牌 deck composing
2. 真正的打牌

組卡先跳過,先假設都用預設套餐
組牌其實沒啥好說的,就自己挑 50 張
順序可以自由決定

先講真正的打牌。兩種模式,合作或對戰
合作先跳過,因為算是特例情況,對戰是對稱的規則比較容易想

準備工作。牌庫自己決定順序,正面朝上,其實就是不需要牌背的意思。
以後可以想想看怎麼利用兩面都可用的卡片來呈現資訊
手牌 5 張。所以一開始就是手上 5 張,牌庫 45 張
順序全部都是已知的,所以也沒有機率可言。
任何玩家都可以知道任何玩家的順序,只要不嫌麻煩去翻的話

玩家受到傷害時,丟牌庫的牌。丟到沒有就輸了

卡分兩種,分別是 summoning spell 和 elemental spell
前者對應 magic 裡的 creature spell, 後者對應 instant spell

每個回合分兩個階段 (phase)
第一個階段是 creature 的行動
第二個階段是放 spell 的行動,或是抽牌的行動
抽牌可以直接從牌庫頂抽到手牌上限,這個動作對應 spellbook 中的謄寫
或是!從牌庫中任意挑出手牌上限的牌,並置於牌庫頂
(對應 spellbook 中把法術抄在 index 上)
也就是說,下回合就可以直接抽剛剛選好的牌(們)

施展 spell 需要的 cost 範圍限制在 1~10 之間
每放棄一張牌,獲得相對應 10-x 的能量
也就是說一張 1 cost 的牌,discard 之後可以獲得 9 點能量
每放棄一張 5 cost 的牌,就可以施展一個 5 cost 的 spell

每次行動可以放棄任意數量的牌,並施展任意數量的 spell
要有 mana burn 嗎?暫時不要好了,但也不能累積
我希望是不要去記任何數字,也不要用 token

生物牌先不談特殊能力,上面會有四個數字。
* cost
* energy (10 - cost)
* melee damage
* magic damage

召喚生物時,放置在場上需要選擇列隊
一個玩家有三個列隊。召喚出來的可以選擇放在列隊最前面,或是最後面,
但不能放在中間。

生物行動時,需要選擇攻擊目標。目標有四種選擇,
其中三種就是三個列隊,第四種是玩家本體。
每一個列隊要選擇使用 melee attack 或 magic attack,
前者攻擊列隊的話,從列隊前面開始攻擊;後者從後面開始
一個列隊一次行動只能選擇 melee or magic, 不能混搭
三個列隊可選擇不同的 melee or magic, 不需要三個列隊都一樣

生物生命即 cost. 例如 5 cost 的生物如果有 5 melee/magic damage,
那就是剛好打死。被打死的話,攻擊方可以回收 energy,
點數等同於 cost
(所以玩家也可以試著打死自己人以取得 energy)

戰鬥結算。雙方同時攻擊,跟 magic 一樣。守方只能用 melee 防守,
因此攻方永遠從前面開始受傷,守方則看是被哪種攻擊攻擊

玩家受到攻擊時,可由列隊後方的生物防禦,數量不限,
唯不得跳過中間的生物。只有玩家受到傷害時需要丟牌庫

攻擊過後的列隊不可攻擊。

啊,我忘記 summoning sickness.
有算進這個規則的話,生物行動和放魔法的順序可以反過來
重點就是不能讓先動的玩家又放生物又攻擊就是了
這個就看看是反過來的順序好,或是 summoning sickness 比較好

大致上先這樣。如何組「卡」還需要多想。
目前是在想每張卡可以有 10 點點數去分配。
能力卡和屬性卡還在思索

元素屬性也還在思索,元素相剋這個是一定會有的

2011-11-19

深入淺出 hello world (llvm toolchain?)

updated 2011-11-19 03:18
對了,我是看到這個才忽然想弄這個的
JVM JIT for Dummies
(What the JVM Does With Your Bytecode When You're Not Looking)


*

第一個當然是想到 jserv 的:

「深入淺出 Hello World Part I/II (台北場次)」簡報上線
演講:深入淺出Hello World (完結篇)

完全沒有感到居然已經這麼多年了啊..? 總之當初看到,大概都只粗略翻過去而已,
因為從來沒碰過這麼底層,所以很多東西看不懂,興趣也沒有說非常多。不過人
總是會想換口味,昨天很發神經地就想瞧瞧一個程式到底是怎麼運作的?

於是我寫了一個 hello world, 利用 clang compile 成 llvm bitcode:

clang -emit-llvm main.c -c -o main.bc
可以用 lli 跑跑看:
lli main.bc
接著瞧瞧相對應的 llvm assembly 長什麼樣子?
llvm-dis main.bc -o main.ll
其實我原本是直接叫 clang 輸出 llvm assembly:
clang -emit-llvm main.c -S -o main.ll
lli 也同樣可以執行 llvm assembly:
lli main.ll
可以再用 llvm-as 把 llvm assembly 編成 llvm bitcode:
llvm-as main.ll -o main.bc
接著用 llc 把 llvm bitcode 編成真正的 assembly:
llc main.bc -o main.s
再用 as 把 assembly 編成 object file:
as main.s -o main.o
最後一步則是靠 ld 把執行檔做出來... 我想知道的地方大概是從這邊開始

直接 ld main.o 很自然會找不到 printf (_printf) 的定義,畢竟這是 libc 的東西。
在 mac 上,大概就這樣 link libc:
ld main.o /usr/lib/libc.dylib
於是會吐出這個錯誤訊息:
ld: entry point (start) undefined.  Usually in crt1.o for inferred architecture x86_64
我想這大概是程式的進入點吧,於是我先試這個:
ld main.o /usr/lib/libc.dylib -e main
不過 main 沒有被定義。我不知道為什麼要叫 _main:
ld main.o /usr/lib/libc.dylib -e _main
這樣就可以了。試著執行看看:
./a.out
跑是跑得起來,有印出字,但是程式要離開時就死了:
fish: Job 1, './a.out ' terminated by signal SIGSEGV (Address boundary error)
我猜是直接去執行 main 的話,有些 OS 需要的程序就被跳過了,
因此會當掉。所以大概是要去找剛剛那個 crt1.o
ld main.o /usr/lib/libc.dylib /usr/lib/crt1.o
這樣確實就沒有任何錯誤了,運作都很正常。
crt1 可能是 c runtime 的意思吧?那個 1 就不知道了。

不過同樣的事情,在 arch linux 上就沒那麼順利了......
一樣先從最基本的開始:
ld main.o
會找不到 printf (這次沒有底線了!), 符合預期
ld main.o /usr/lib/libc.so
會吐出警告:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400270
大概是假設 _start 會在某個位置吧。這個 _start 應該跟 mac 的
entry point (start) 是差不多的意思。所以我應該去找 crt1.o
ld main.o /usr/lib/libc.so /usr/lib/crt1.o
這下可好了,還有東西沒有 link 到...
/usr/lib/crt1.o: In function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
/usr/lib/crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
我找很久,用 grep /usr/lib 後找到很多可疑的檔案,但還是不知道怎麼搞...
只好觀察:
gcc -v main.c
裡面用了 collect2 而不是 ld? 我不知道有什麼差...
總之就抄他要 link 哪些東西吧?中間過程跳過,反正我搞很久...... 最後:
ld main.o /usr/lib/libc.so /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o /usr/lib/libc_nonshared.a
這也實在是太多東西,太不方便了吧 :( 總之這樣 ld 就不會抱怨了,但執行起來...
fish: Failed to execute process './a.out'. Reason:
fish: The file './a.out' or a script or ELF interpreter does not exist, or a
shared library needed for file or interpreter cannot be found.
我就卡在這不知道要怎麼繼續下去了。搞了好幾個小時(像神經病一樣),
還是看不出來怎麼做可以讓他的訊息有點變化。更可怕的是,如果用:
ldd a.out
還會吐出莫名其妙的訊息:
/usr/bin/ldd: line 118: ./a.out: No such file or directory
感覺是 bash 的問題啊!!!
bash -c ./a.out
會吐出:
bash: ./a.out: No such file or directory
但是 fish 都好好的沒問題。bash 的版本是 4.2.10

程式在這 llvm/build.sh + llvm/main.c

2011-09-28

copying table to table efficiently in postgres

Here's the background. I want to merge three tables into one,
and I don't care about primary keys. Also, we need to leave a
metadata to record where the record is copied from.

We are using PostgreSQL and ActiveRecord. The latter is not
important, it's just a convenient tool. All the tricks are inside SQL.

Suppose we have "From" model and "froms" table, and we want to
copy to "To" model and "tos" table in this case. Then we'll do:

columns = From.columns.inject([]){ |r, i|
  r << i.name if i.name != 'id'
  r
}
conn = ActiveRecord::Base.connection
puts "Dumping #{From}..."
conn.query(<<-SQL)
  COPY
  (SELECT #{columns.join(', ')}, '#{From.table_name}' FROM #{From.table_name})
  TO '/tmp/path-to-intermediate-file'
SQL
#                                ^^^^this is the metadata
puts "Restoring #{To}..."
conn.query(<<-SQL)
  COPY
  #{To.table_name}(#{columns.join(', ')}, from_table)
  FROM '/tmp/path-to-intermediate-file'
SQL
#                                ^^^^this is the metadata
Previously, I am running ActiveRecord with batch find and inserts.
(because that's what others did previously)
I run it overnight and it hadn't finished...
Now with COPY it runs in minutes!
36000 seconds => 120 seconds. It's 30000% improvement....

This reminds me once Heroku was using taps to transfer database.
That is awfully awfully awfully slow and I must say stupid.

At that time, I wrote an eventmachine based receiver and use
Heroku console to send data in batch. It's not very convenient to
use it, since some tunneling is also involved, but it also runs about
30000% or even more faster....

I guess they don't need to handle large data...

2011-09-18

blog + personal wiki 計畫 (0)

之前在 buzz 的討論:

我的理想上是這樣...

1. blog 本身要像 wiki 一樣,可以用很簡單的方式互相索引,
也能很簡單地調整頁面編排,而不是像 blog 那樣單純用時間

2. 資料本身用 git 儲存,每次編輯就是一次 commit,
每篇文章就是一個 file, 三種格式,markdown or html or plain/text

3. comment 是 markdown or plain/text 格式,一樣寫入 file
假設文章是叫 home, 則產生目錄 home/post.md
home/comments-00.md, home/comments-01.md, ...
deploy 自動產生 home/index.html, 把 post 跟 comments 串起來
comments 太多的話可以再分頁 home/index-01.html

所以操作流程是這樣... 要寫新東西,就在 local 編輯,
然後 commit 後 push 至 server, 然後 deploy 產生 html
或是 local 端 deploy 然後自己再把輸出 **/*.html 上傳

發生 comment 時,則在 server 上 commit, 然後重新 deploy 該文章

也就是說,除了 static page 以外,還有有一個程式
負責接 comment 的產生。這個可以開或關,在 deploy 時決定
關閉的話就不產生 comment form, 打開時就產生

大概是這些吧.... 調整版面什麼的,自然又是另一回事了

暫定 site directory, 嗯,第一版先沒有 comment 好了
generated, hand written

archive/2011-09/index.html
archive/2011-09/index-1.html
post/hello-world/post.md
post/hello-world/index.html # e.g. murmur (42)
post/最好支援 unicode/post.md
post/最好支援 unicode/index.html
site/feed.atom # e.g. /feeds/posts/default
site/feed.rss
site/index.html # e.g. blogger.godfat.org
site/index-1.html # e.g. page 1
site/titles.html # e.g. 0rz index
tag/程式/index.html
tag/程式/index-1.html
theme/index/css.scss
theme/index/html.erb
theme/index/js.coffee
theme/post/css.scss
theme/post/html.erb
theme/post/js.coffee
config.ru

先有 static site generator 即可,第二階段是跑 application server
可以在線上修改 post 和接受 comments.

2011-07-31

做投影片

這篇一開始貼在 buzz, 後來貼在 google+, 這邊稍微重新編輯一下

2011-07-27 4:46:03 AM

前情提要:為了這次 rubyconf.tw/2011 要做新的投影片,
這次想嘗試一下不一樣的作法,因為老是用 apple keynote 做投影片讓我害怕,
害怕的點跟用 powerpoint 半斤八兩。其實我對 keynote 還算是滿意,
雖然要做龜毛投影片有點困難,但要快速做出還可以看的投影片,
算是滿容易的。自己覺得 keynote 最好,其他軟體很少有的功能是
snap 的部份。keynote 的 snap 功能滿好用的,可以很快對齊各種點,
不管是投影片的中心,或是相對於其他物件的中心,都滿容易拉的。

那麼如果要換軟體,換什麼軟體好?後來我自己是滿喜歡 markdown,
寫起來很簡潔,就算是純文字的瀏覽效果也不錯。所以就想找 markdown
轉投影片的軟體。一開始是找到 slidedown

這是在我正式決定改找其他軟體做投影片之前就找到過的。那時候試用
是覺得缺不少東西,版面也很難調整,所以放棄回到 keynote. 這次看了看,
大概還是不能用吧,所以想再找別的。明明之前就有看過幾個所謂 html5 的
投影片做得還可以...

後來看到這個投影片:
The state of the art of nginx.conf scripting
(p.s. nginx 玩成這樣真是沒話說! ngx_openresty)
老林說是用這個做的: slides.htm

雖然他處理了字型的問題還不錯,不過之前試要跑起來有點複雜,文字格式
我也不是很習慣,再加上翻頁會閃動的狀況,至少在我電腦上實在太嚴重了。
想想就還是算了。最後終於找到: landslide

這應該就是那個很炫的 html5 的投影片用的工具。原本居然還是 google 的人
寫的。基本上用起來還滿單純的,也有整合 pygment, 目前我覺得最好的
syntax highlighter. 所以除去小毛病的話,這大概就是我想要的理想方法吧。
用 markdown 寫投影片,用簡單地方式做 syntax highlight, 想我當初在 keynote
裡自己用手一個個上色,還用取色工具確保上的顏色跟 TextMate 一樣,
真是超辛苦的 =_= 而 pygment 我原本也有做一份 twilight 的 theme,
真要用的話也是沒有問題的,雖然可能有版本問題要再稍微調整一下。
pygmentize

landslide 輸出的 html 基本上是打成一包的,embed javascript, css, 甚至連
圖片都用 base64 全部 embed 進去,所以攜帶性應該是還可以。他甚至可以
輸出 pdf! 不過是透過另一個軟體,把 html 再轉成 pdf: princexml
試了一下,基本上結果有點慘不忍睹,算了。要試可以用 homebrew 灌,
參考: Add Prince
brew install https://github.com/adamv/homebrew-alt/raw/master/non-free/princexml.rb
或是新版:
brew install https://raw.github.com/godfat/homebrew/e7bb2f0268859d7fc3d1ebad8b3aac17d7642d6a/Library/Formula/prince.rb

總之,那麼接下來就是尋找畫圖表的工具了。把製作投影片跟圖表的工具
分開,應該也是一個不錯的決定吧。可惜一直不順利。在 google+, twitter,
和 facebook 上詢問,好像只有在 twitter 沒得到回應?很感謝大家。總之
說實在要錢的懶得試,好幾個線上的則有點彆手彆腳,應該能用,但總覺得
好像少了點什麼決定性的關鍵。後來找到了: Dia
用起來是還可以,雖然在 mac 上跑 x11 實在不太順。試做的圖見圖一。

本來是決定要用 dia, 但後來忽然發現輸出的圖片難以決定大小!試了很多方式,
用各種方式輸出,最後有一個方法是輸出 svg, 然後再用 svg2png (brew install svg2png)
輸出即可決定大小。但是還是不對,因為那是按照比例 scale 的,這使得
輸出的圖大小雖然相同,但圖表比例卻不一樣...。

然後感謝 ET Blue, 我試了 LibreOffice, 不過這要控制輸出大小更是...
預設是 A4, 我該說啥,好像完全不適合拿來做圖片。沒試多久就覺得不太對。
不過功能本身是滿強的,要輸出的話應該可以用吧...

最後最後,我試到 InkScape
這套軟體是我目前用過跑在 mac 的 x11 上效果最好的!雖然終究是 x11,
所以用起來還是很怪又不太順,但以 x11 能做到這樣真的已經讓人讚嘆了...
只能說 apple 的 x11 支援還是很差吧,雖然我猜也沒人在意。

結果如圖二。我承認我畫得很醜,但至少滿足我的要求了。能控制輸出大小,
比例不能亂跑,位置可以控制,大概就這樣吧。真是奇哉怪也,明明要求不多,
卻很難找到軟體能符合這些要求。總之我後來就決定用 inkscape.

故事還沒結束。瞧還有圖三吶。既然我妹願意幫我做,何不讓他試試?
一方面應該能做得美觀許多,另一方面我也能省下點時間,老是在
那邊刻圖表我也覺得很煩啊。結果就是圖三了,用 illustrator 做的。
說來 illustrator 好像也沒有比 inkscape 好..。跟他在那邊弄半天,
位置老是沒辦法對齊,也似乎不能輸入座標?輸出成圖片位置又會跳動,
實在是完全不知道該說什麼。雖然說或許這就是 vector 的天限,但輸出
pdf 效果很好,真不知道為什麼輸出圖片就怪怪的,位置會有些微偏差。

嘛,也罷,反正圖表本身我是還滿滿意的,稍微抖動的問題就再說吧...
大不了乾脆整個用 illustrator 做,然後輸出 pdf 就可以有完美結果了 :/
只希望不要再調整位置了,我真搞不懂為什麼 illustrator 要調整位置有
這麼痛苦。說真的,我現在非常認真覺得 flash 是個很棒的繪圖工具...
早知道搞不好乾脆一開始就用 flash 做算了,調位置很容易,可以輸入
座標,東西也能做成 symbol, 不用改一個鬼就要動十個鬼,實在是...

繪圖也要模組化啊!(暈)

總之總之,就這樣用 landslide 和 illustrator 的輸出圖搭配看看...。
希望能順利把投影片做完就是了。

p.s. 結果其實程式都還沒完全寫完哩。 rest-core
不過也罷,反正想看程式的人根本不多... 慢慢來就是了 :s

reference:
google+ thread #0
google+ thread #1

2011-06-09

ssh tunneling tcp/port forwarding

It's so hard to remember all those commands :(
note: [bind host] is usually localhost, and could be omitted

SOCKS proxy (dynamic):
ssh -D [bind host:]{bind port} {remote host}
e.g. ssh -D 1234 my-server.com
SOCKS proxy is at localhost:1234

port forwarding (local):
ssh -L [bind host:]{bind port}:{target host}:{target port} {remote host}
e.g. ssh -L 1234:ptt.cc:22 my-server.com
connect to ptt with ssh://bbs@localhost:1234

reverse tunneling (revere, needs GatewayPorts):
ssh -R [bind host:]{remote port}:{target host}:{target port} {remote host}
note: target host is usually localhost
e.g. ssh -R 41829:localhost:8080 my-server.com
now my-server.com:41829 is acting as localhost:8080
(set sshd_config GatewayPorts yes)



All texts are licensed under CC Attribution 3.0