Joker 2025-08-18T20:15:19+00:00 kejinlu@gmail.com Process Substitution Example 2025-08-18T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Process-Substitution-Example wc <(cat /usr/share/dict/linux.words) Here is the output: 483523 483523 4992010 /dev/fd/63. Could you explain me about the steps how the bash executes this command.

You’re asking Bash to run wc (word count) on the output of cat /usr/share/dict/linux.words without creating a file. You’re using process substitution (<(…)) to achieve this.

✅Step 1: Bash Sees the <(…) Bash recognizes <(cat /usr/share/dict/linux.words) as process substitution — a special syntax. Instead of passing the command’s output directly, Bash will: Run cat /usr/share/dict/linux.words in the background, and Make its output available via a named pipe or /dev/fd/N file descriptor.

✅Step 2: Bash Creates a File Descriptor Bash creates something like: /dev/fd/63

This is a symbolic link to a file descriptor created by Bash (usually through /proc/self/fd/63), pointing to the output of cat. 📌 File descriptors are special kernel objects that represent open files or pipes. /dev/fd/N is a way to refer to them as filenames.

✅ Step 3: Bash Replaces the Command

So the command becomes effectively: wc /dev/fd/63 But /dev/fd/63 is not a regular file — it’s a pipe that streams the output of: cat /usr/share/dict/linux.words

✅ Step 4: wc Runs on the Stream Now wc sees a normal file argument: wc /dev/fd/63 It reads from that file descriptor (which is the stream from cat) and prints: 483523 483523 4992010 /dev/fd/63

Which means: 483523 lines 483523 words 4992010 bytes Source: /dev/fd/63 (the temporary file descriptor Bash created)

Recap of What Bash Does Internally

  1. Detects <(…)
  2. Starts cat /usr/share/dict/linux.words in background
  3. Connects its output to a temporary file descriptor, like /dev/fd/63
  4. Runs wc /dev/fd/63
]]>
Kokoro Code Chinese 2025-08-18T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Kokoro-code-Chinese
# This file is hardcoded to transparently reproduce HEARME_zh.wav
# Therefore it may NOT generalize gracefully to other texts
# Refer to Usage in README.md for more general usage patterns

# pip install kokoro>=0.8.1 "misaki[zh]>=0.8.1"
from kokoro import KModel, KPipeline
from pathlib import Path
import numpy as np
import soundfile as sf
import torch
import tqdm

REPO_ID = 'hexgrad/Kokoro-82M-v1.1-zh'
SAMPLE_RATE = 24000

# How much silence to insert between paragraphs: 5000 is about 0.2 seconds
N_ZEROS = 5000

# Whether to join sentences in paragraphs 1 and 3
JOIN_SENTENCES = True

VOICE = 'zf_001' if True else 'zm_010'

device = 'cuda' if torch.cuda.is_available() else 'cpu'

texts = [(
"白日依山尽",
), (
"黄河入海流",
), (
"欲穷千里目",
), (
"更上一层楼",
)]

if JOIN_SENTENCES:
    for i in (1, 3):
        texts[i] = [''.join(texts[i])]

en_pipeline = KPipeline(lang_code='a', repo_id=REPO_ID, model=False)
def en_callable(text):
    if text == 'Kokoro':
        return 'kˈOkəɹO'
    elif text == 'Sol':
        return 'sˈOl'
    return next(en_pipeline(text)).phonemes

# HACK: Mitigate rushing caused by lack of training data beyond ~100 tokens
# Simple piecewise linear fn that decreases speed as len_ps increases
def speed_callable(len_ps):
    speed = 0.8
    if len_ps <= 83:
        speed = 1
    elif len_ps < 183:
        speed = 1 - (len_ps - 83) / 500
    return speed * 1.1

model = KModel(repo_id=REPO_ID).to(device).eval()
zh_pipeline = KPipeline(lang_code='z', repo_id=REPO_ID, model=model, en_callable=en_callable)

path = Path(__file__).parent

wavs = []
for paragraph in tqdm.tqdm(texts):
    for i, sentence in enumerate(paragraph):
        generator = zh_pipeline(sentence, voice=VOICE, speed=speed_callable)
        f = path / f'zh{len(wavs):02}.wav'
        result = next(generator)
        wav = result.audio
        sf.write(f, wav, SAMPLE_RATE)
        if i == 0 and wavs and N_ZEROS > 0:
            wav = np.concatenate([np.zeros(N_ZEROS), wav])
        wavs.append(wav)

sf.write(path / f'HEARME_{VOICE}.wav', np.concatenate(wavs), SAMPLE_RATE)
]]>
眼睑肿胀 2025-08-17T00:00:00+00:00 Joker http://robustness.github.io/2025/08/眼睑肿胀 从中医角度分析,眼睑肿胀若由细菌感染引起(如麦粒肿、睑缘炎等),多与风热外袭、脾胃湿热或热毒上攻有关。以下是中医的辨证调理和治疗方法:


一、中医辨证分型与应对

1. 风热外袭(初期红肿热痛)

  • 表现:眼睑局部红肿、发热、微痒,可能伴头痛、发热。
  • 治疗原则:疏风清热。
  • 方法
    • 内服:银翘解毒片、桑菊饮(桑叶、菊花、薄荷等)。
    • 外敷:野菊花、蒲公英煎水凉湿敷(清热解毒)。

2. 脾胃湿热(肿胀反复、脓液黏稠)

  • 表现:眼睑红肿硬结、分泌物黄稠,口干口臭、便秘。
  • 治疗原则:清热化湿、通腑泄热。
  • 方法
    • 内服:黄连上清丸、甘露消毒饮(黄芩、栀子、茵陈等)。
    • 饮食:忌辛辣油腻,多吃冬瓜、薏米、绿豆。

3. 热毒壅盛(化脓期)

  • 表现:肿胀剧烈、跳痛明显,脓头形成。
  • 治疗原则:清热解毒、排脓消肿。
  • 方法
    • 内服:五味消毒饮(金银花、蒲公英、紫花地丁等)。
    • 外治:脓成后需由医生刺破排脓,切勿自行挤压!

二、中医外治法推荐

  1. 中药熏洗
    • 方剂:蒲公英30g+金银花20g+野菊花15g,煎水后趁热熏眼,待温后湿敷。
    • 作用:抗菌消炎、消肿止痛。
  2. 穴位刺激
    • 耳尖放血:消毒后针刺耳尖挤出2-3滴血,可泻热解毒(需专业人员操作)。
    • 按压穴位:合谷(手背)、太阳穴(颞侧)、攒竹(眉头),每穴按压1分钟,每日2次。
  3. 青敷药膏
    • 金黄散(大黄、黄柏等研粉调糊)外敷患处,适用于未溃脓时(避开眼睛)。

三、生活调护建议

  1. 饮食禁忌
    • ❌ 忌辛辣(辣椒、羊肉)、发物(海鲜、韭菜)、甜腻食物。
    • ✅ 宜清淡:苦瓜、黄瓜、梨、荸荠等清热食材。
  2. 起居注意
    • 避免熬夜(伤阴助火),保持大便通畅(肺与大肠相表里,热毒易上攻)。
    • 勿用脏手揉眼,毛巾需煮沸消毒。

四、何时需结合西医?

中医调理适用于轻中度感染,若出现以下情况需中西医结合治疗:

  • 肿胀化脓未自行破溃,或发热不退;
  • 视力受影响,提示感染可能扩散;
  • 反复发作(可能需西医排查螨虫感染或慢性炎症)。

五、简易验方参考

  • 决明子茶:决明子15g+菊花10g,泡水代茶饮(清肝明目)。
  • 马应龙八宝眼膏(含炉甘石、冰片等):外用缓解红肿(需避开眼球)。

建议先辨证明确体质后再用药,若自行处理2-3天无缓解,务必就诊中医眼科或结合西医抗感染治疗。

]]>
V2ray Setup 2025-08-17T00:00:00+00:00 Joker http://robustness.github.io/2025/08/V2Ray-setup Got it — you want Approach 3: Shadowsocks / V2Ray because that’s the one that’s most likely to work well in China. I’ll give you a detailed, step-by-step guide to set up V2Ray on Ubuntu, optimized for bypassing the Great Firewall.

We’ll go for VLESS over TCP + TLS (very stealthy — it looks like normal HTTPS traffic).


Step 1 — Update Your Ubuntu Server

sudo apt update && sudo apt upgrade -y

Step 2 — Install Required Tools

We’ll need curl, socat, wget, unzip, and uuid-runtime:

sudo apt install curl socat wget unzip uuid-runtime -y

Step 3 — Get a Domain Name

To make V2Ray harder to detect, you must use a domain name pointing to your server’s public IP.

  • Buy a domain (e.g., from Namecheap, Cloudflare, or Alibaba Cloud).
  • Create an A record for vpn.yourdomain.com → your server’s IP.
  • Wait for DNS to propagate (can check with ping vpn.yourdomain.com).

Step 4 — Install V2Ray via Official Script

bash <(curl -sL https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)

This will:

  • Download the latest V2Ray binaries
  • Install them into /usr/local/bin
  • Set up a systemd service

Step 5 — Get a TLS Certificate (HTTPS)

We’ll use acme.sh (lightweight Let’s Encrypt client):

# Install acme.sh
curl https://get.acme.sh | sh
# Issue a certificate for your domain (replace with your actual domain!)
sudo systemctl stop nginx
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
~/.acme.sh/acme.sh --issue -d vpn.futurelei.com --standalone --keylength ec-256
sudo systemctl start nginx

# Install the certificate into /etc/v2ray/
sudo mkdir -p /etc/v2ray/
~/.acme.sh/acme.sh --install-cert -d vpn.yourdomain.com \
  --ecc \
  --fullchain-file /etc/v2ray/v2ray.crt \
  --key-file /etc/v2ray/v2ray.key
  • Issue 0: When I run the step 5, I got the following: touch: cannot touch ‘/etc/v2ray/v2ray.key’: No such file or directory

When I run step, will it generate a folder /etc/v2ray/ ?

  • Solution 0: sudo mkdir -p /etc/v2ray/

Step 6 — Configure V2Ray (VLESS over TCP+TLS)

Edit the config file:

sudo nano /usr/local/etc/v2ray/config.json

Paste this config (replace UUID-GOES-HERE with a generated UUID and vpn.yourdomain.com with your domain):

{
  "inbounds": [{
    "port": 443,
    "protocol": "vless",
    "settings": {
      "clients": [{
        "id": "29c23e6b-e7fa-414b-ab30-6015d17b2fe3",
        "level": 0,
        "email": "user@v2ray"
      }],
      "decryption": "none"
    },
    "streamSettings": {
      "network": "tcp",
      "security": "tls",
      "tlsSettings": {
        "certificates": [{
          "certificateFile": "/etc/v2ray/v2ray.crt",
          "keyFile": "/etc/v2ray/v2ray.key"
        }]
      }
    }
  }],
  "outbounds": [{
    "protocol": "freedom",
    "settings": {}
  }]
}

Step 7 — Generate Your UUID

uuidgen

Copy that UUID and replace UUID-GOES-HERE in the config.


Step 8 — Start & Enable V2Ray

sudo systemctl enable v2ray
sudo systemctl restart v2ray

Check if it’s running:

sudo systemctl status v2ray

Step 9 — Client Setup

On your device (Windows, Mac, Android, iOS):

  • Install V2RayN (Windows) or Shadowrocket (iOS) or V2RayNG (Android).
  • Add a VLESS server:

    • Address: vpn.yourdomain.com
    • Port: 443
    • UUID: (the one you generated)
    • Encryption: none
    • Transport: TCP
    • TLS: enabled

Step 10 — Test

Connect in your client, then check your IP:

curl ifconfig.me

It should show your server’s IP (not your local one).


💡 Extra Tips for China

  • If VLESS over TCP+TLS still gets blocked, we can add WebSocket+TLS or XTLS to make it look exactly like normal web traffic.
  • You can also run Nginx as a fake website in front of V2Ray so casual observers only see a normal HTTPS page.

If you like, I can give you a ready-made install script that:

  • Installs V2Ray
  • Gets TLS cert automatically
  • Configures VLESS+TLS with WebSocket fallback

That’s faster and less error-prone than doing each step manually. Do you want me to prepare that script for you?

]]>
Process Substitution 2025-08-17T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Process-Substitution This command uses process substitution (<(command)) to pass the output of curl as a file-like input to bash. Let’s break it down:

What’s Happening?

bash <(curl -sL https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)
  1. curl -sL <URL>
    • Fetches the script (install-release.sh) from the given URL.
    • -s = Silent mode (no progress/errors shown).
    • -L = Follow redirects (if any).
  2. Process Substitution (<(...))
    • <(command) creates a temporary named pipe (FIFO) or /dev/fd file descriptor containing the output of curl.
    • Instead of saving the script to disk, Bash treats the output as a temporary “file” for input.
  3. bash <file>
    • The script is executed directly by bash without being saved to disk.

Why Use Process Substitution?

  • No Temporary File Needed
    Avoids writing the script to disk (cleaner, no cleanup required).
  • Security Consideration
    Prevents tampering (if the script were saved, malware could modify it before execution).
  • One-Liner Convenience
    Combines download + execution in a single command.

Alternatives (Without Process Substitution)

# Download to a file, then run (less secure)
curl -sL https://.../install-release.sh -o install.sh
bash install.sh
rm install.sh  # Cleanup

# Pipe directly (no process substitution)
curl -sL https://.../install-release.sh | bash
  • Piping (| bash) works but may miss script features (e.g., $0 detection fails).
  • Process substitution preserves script behavior as if it were a local file.

Key Takeaway

Process substitution (<()) is used here to treat the downloaded script as a file without saving it, combining safety and convenience. It’s a common pattern for remote script execution.

]]>
Github Personal Website Dns Setup 2025-08-17T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Github-Personal-Website-DNS-Setup Great! Since you’re using Blacknight in Ireland for your domain registrar, here’s how to connect your custom domain to your GitHub Pages site step by step:


Step 1: Configure DNS on Blacknight

A) Determine your control panel type:

  • If your account was created after June 2022, you’ll use the new interface at cp.blacknighthosting.com.
  • Otherwise, you’ll use the older panel at cp.blacknight.com (help.blacknight.com).

B) Log in:

  • For new interface: go to Domains → Manage DNS → Edit Zone for your domain (help.blacknight.com).
  • For older panel: go to Home → Hosted Domains → select your domain → Web → Remove Hosting, then switch to the DNS tab (help.blacknight.com).

C) Add the required DNS records:

  1. Add four A records for the root domain (leave the “Domain” field blank or use @):

  2. Add a CNAME record for the www subdomain:


Step 2: Add the Custom Domain on GitHub

  1. Open your repository on GitHub that hosts your Pages site.
  2. Go to Settings → Pages.
  3. In the Custom domain field, enter your full domain (example.com or www.example.com) and click Save.
  4. This action creates a CNAME file in the repository automatically (Medium, GitHub Docs).

Step 3: Wait for DNS Propagation & Enable HTTPS

  • DNS changes can take up to 24 hours to propagate fully (Medium, Reddit).
  • After propagation, return to your GitHub Pages settings and check “Enforce HTTPS” to secure the site.

Quick Recap

Step Action
1 Log in to relevant Blacknight control panel
2 Remove any hosting or forwarding
3 Add A records (four GitHub IPs) and CNAME for www
4 Add the custom domain in GitHub Pages settings
5 Wait for DNS to update, then enable HTTPS

Let me know if you’d like help navigating the Blacknight interface or screenshots for the new or old panel. Happy to guide you through any step!

]]>
Assess Chatgpt Cmd 2025-08-17T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Assess-chatgpt-CMD Yes — you can absolutely interact with ChatGPT (or GPT-5 in this case) from a remote server via the command line, but you’ll need to go through the OpenAI API (or an API-compatible service) rather than the web chat UI.

Here’s the high-level process:


1. Get API Access

  • Sign up at OpenAI (if you don’t have an API key yet).
  • Go to View API keys in your account settings.
  • Copy your API key — you’ll use it for authentication.

2. Install Required Tools

On your remote server (Linux, macOS, or WSL), you can install the OpenAI Python package or just use curl.

Option A — Python (Recommended)

pip install openai

Option B — Using curl (no extra install needed, just basic shell)


3. Example — Command Line via curl

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "gpt-5",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Hello from my remote server!"}
    ]
  }'

4. Example — Python Script

from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY")

response = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello from my remote server!"}
    ]
)

print(response.choices[0].message["content"])

5. Bonus — Make It an Interactive CLI Chat

You could create a small script like:

from openai import OpenAI
import os

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

while True:
    prompt = input("You: ")
    if prompt.lower() in ["exit", "quit"]:
        break
    response = client.chat.completions.create(
        model="gpt-5",
        messages=[{"role": "user", "content": prompt}]
    )
    print("GPT:", response.choices[0].message["content"])

Run it:

export OPENAI_API_KEY="your_api_key_here"
python cli_chat.py

You’ll get an interactive terminal chat with GPT-5 from your remote server.


If you want, I can also give you a ready-to-use Bash-only one-liner that lets you talk to ChatGPT in the terminal without Python at all. That’s handy for quick server interactions.

Do you want me to prepare that one-liner version?

]]>
Quicktime 2025-08-16T00:00:00+00:00 Joker http://robustness.github.io/2025/08/quicktime Here’s a clear breakdown of QuickTime recording shortcuts on macOS:


🎥 Screen Recording (using macOS built-in tools)

QuickTime itself doesn’t have dedicated shortcuts, but Apple added Shift + Command + 5 to bring up the Screen Capture/Recording toolbar:

  • Shift + Command + 5 → Open recording controls (choose “Record Entire Screen” or “Record Selected Portion”)
  • Command + Control + Esc → Stop recording immediately

👉 These are the fastest built-in shortcuts. Behind the scenes, they use QuickTime’s recorder.


🎤 Audio/Video Recording (inside QuickTime Player)

No direct global hotkeys exist, but within QuickTime Player:

  • Option + Command + N → New Screen Recording
  • Control + Option + Command + N → New Audio Recording
  • Command + Option + N (older versions) → New Movie Recording

⚠️ Note: Pause is not available in QuickTime. You can only Start or Stop. To mimic “pause,” record multiple clips and merge them in QuickTime (Edit → Add Clip to End).


✅ If you want real Pause/Resume hotkeys

You’ll need a third-party app like:

  • OBS Studio (free, customizable hotkeys)
  • ScreenFlow / Camtasia (paid, professional, with pause/resume support)

Do you want me to write you an AppleScript + Automator/Shortcuts workflow so you can trigger QuickTime recording with a single keystroke (like F9 to start, F10 to stop)? That’s possible.

]]>
Upgrade Ubuntu 22.04 to 24.04 in Ubuntu Server 2025-08-16T00:00:00+00:00 Joker http://robustness.github.io/2025/08/Upgrade-Ubuntu-22.04-to-24.04 Since you’re on Ubuntu 22.04 LTS (Jammy Jellyfish), the next LTS release is Ubuntu 24.04 LTS (Noble Numbat). Upgrading between LTS versions is officially supported and relatively straightforward, but it’s important to follow the right steps.

Here’s the recommended process:


1. Update your current system

sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoremove --purge -y

This ensures you have all the latest patches for 22.04 before upgrading.


2. Check and install the upgrade tool

sudo apt install update-manager-core

Make sure /etc/update-manager/release-upgrades has:

Prompt=lts

3. Start the upgrade

Since you want latest LTS, run:

sudo do-release-upgrade

If it says “No new release found” (because 24.04 upgrades from 22.04 may not be offered immediately for servers), you can force it:

sudo do-release-upgrade -d

The -d flag forces an upgrade to the latest development release, but after April 2024, 24.04 is considered stable, so it just points to Noble Numbat.


4. Follow the prompts

  • The process will download packages, then ask about replacing config files — usually safe to accept the new versions unless you have custom changes.
  • Server upgrades will temporarily disable third-party PPAs; you can re-enable them later.

5. Reboot

sudo reboot

6. Verify version

lsb_release -a

You should see:

Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:        24.04
Codename:       noble

💡 Tip: Always back up /etc/ configs and important data before upgrading in case something breaks.

If you like, I can also give you a one-shot upgrade script that safely does all these steps in sequence. Would you like me to prepare that?

]]>
Software 2020-07-07T00:00:00+00:00 Joker http://robustness.github.io/2020/07/Software MAC OS Installation:
Karabiner ==> map option and cmd key
install xcode
xcode-select —install
install quartz	     
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
brew install caskroom/cask/brew-cask
brew cask install google-chrome
brew cask install dropbox
brew cask install mactex
brew cask install skype
brew cask install evernote
brew cask install sogouinput
brew cask install mactex

brew install youtube-dl

For the Blog

git clone https://github.com/robustness/robustness.github.io
gem install jekyll
sudo gem install jekyll
sudo gem install kramdown

More Configurations

  1. Dropbox:
sudo ln -s ~/Downloads ./Downloads 
Link the Downloads folder to Dropbox
  1. Boom Mendeley MacDJView uTorrent,The Unarchiver, kindle, pdftk, Office 2011, Mathematica 8.0.0 (Be careful about the correctness of the mathID as input), page monitor (a Chrome plugin), matlab

  2. homebrew

brew install tree
brew install wget
brew install astyle
brew install unrar
brew install imagemagick
brew install rename
brew install gfortran
brew install r
brew install graphicsmagick --with-magick-plus-plus
brew install fltk 
brew install gnuplot
brew install ghostscript
  1. How to get an SSH server running on a Mac
Go to System preferences -> Sharing
Check the **Remote Login** box
That is it!
  1. Mail: New messages sound: none; Play sounds for other; mail action; check for new messages manually. Jabber: alerts: play a sound, No! and adjust the sound to the minimal.

  2. Do not install: ntfs-3g, octave (matlab is better)

  • Update Terminal GNOME Fonts
Download Bitstream Vera Mono 1.10
Unzip
double click VeraMono.ttf
click Install Font
open Terminal, click Terminal->Preferences
find Font and click Change
choose Bitstream Vera Sans for Family
Size: 13
relation font choose window(?)
tick to choose Antialias text
reboot terminal
Terminal->Preferences->Settings->Window->Background-> Color and Effects -> Opacity
adjust from 90 - > 70
  • /private/etc/bashrc
`#PS1='\h:\W \u\$ '`
`PS1='\u@\h:\w\$ ‘`

####MAC resources:

  1. http://soft.macx.cn/5134.htm
  2. http://www.mechodownload.com/forum/165-applications/?prefixid=appmacintosh
  3. mechodownload.com or macx.cn

Ubuntu Installation:

a. Change terminal color

b. Install Latex:

sudo apt-get install kile texlive texlive-latex-extra texlive-math-extra texlive-pstricks texlive-science latex-beamer texlive-extra-utils latex-mk fig2ps lmodern texlive-fonts-extra okular jabref

c. Install Matlab

sudo mkdir -p /mnt/Image
sudo mount -o loop disk1.iso /mnt/Image
sudo ./install

Here you need to get rid of one warning by ln -s old new

sudo ln -s ~/Matlab/bin/matlab /usr/bin/matlab
sudo apt-get install ubuntu-restricted-extras
sudo apt-get install chromium-browser

tar xvfz p4v.tgz
cd p4v-2010.2.317255
sudo cp bin/* /usr/bin/ 
sudo cp -r lib/* /usr/lib/

PDFView Command:

okular %.pdf

Changed to

PDFView Command: okular --unique %.pdf

Java:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

####Software to Explore:

Zotero

Network Monitoring Tools

]]>