After interviewing 140 people at the top of their fields, Tim Ferriss has 2 key pieces of advice for 20-somethings starting a career

 

Tim Ferriss said that when you’re starting out in your career, you should focus on “learning instead of earning.”

  • “The 4-Hour Workweek” author and hit podcast host Tim Ferriss has made a career of collecting best practices from people at the tops of their fields.
  • For his new book “Tribe of Mentors,” bestselling author and star podcast host Tim Ferriss sent 11 questions to 140 people at the top of their fields.
  • He said most young people chase money at the expense of learning.
  • He also believes young professionals should focus on adopting skills that can work across industries.

When Tim Ferriss was an undergraduate at Princeton, he saw the majority of his classmates fiercely competing for high-paying consulting and finance jobs, regardless of their personal passions or backgrounds. He knew pretty quickly the path wasn’t for him.

After moving to Silicon Valley and starting his own company, Ferriss took a break from it all and embarked on a journey that resulted in his becoming a self-proclaimed “human guinea pig” who seeks out and learns from people at the top of their fields, from musicians to hedge fund managers, writers to chefs.

We recently spoke with Ferriss for Business Insider’s podcast “Success! How I Did It.” After asking him about his own career and what he learned writing his new book “Tribe of Mentors,” we asked him what he recommended for young professionals just beginning their careers. He had two tips.

1. Initially prioritize learning over money

Ferriss said that it’s worth fighting the urge to go for the job that will get you the biggest paycheck when you’re establishing yourself.

“If you optimize for money too early, you will be minimizing for learning, almost without exception,” he said.

“So look at the first few years out as an apprenticeship where you cover your costs,” he said. “And if you’re looking in business, I would say, be in the room as much as possible to observe the decision-makers and dealmakers.”

He said, for example, that if there were someone interested in technology startups and they had a choice between a 1,000-5,000 person team in a hot company and a fast-growing 30-person team in a field as unsexy as waste management — but with the opportunity to work alongside the leadership team — he’d recommend the garbage industry job without hesitation.

2. Learn transferable skills

He then explained that when undertaking this early career education, it’s worth focusing on the material that will help you when you are ready to start going after high-paying, respected jobs.

Ferriss said that if your job entails something niche like placing ads on Instagram, by all means learn how to do that well, “but spend equal time developing the higher level skills like negotiation, persuasion, copywriting.”

He explained: “These are skills that transfer to many, many other domains, which gives you a lot of flexibility and a lot of leverage.”

Source: http://www.businessinsider.com/tim-ferriss-career-advice-for-20-somethings-2017-11

Advertisements

What does if __name__ == “__main__”: do?

A module’s __name__

Every module has a name and statements in a module can find out the name of its module. This is especially handy in one particular situation – As mentioned previously, when a module is imported for the first time, the main block in that module is run. What if we want to run the block only if the program was used by itself and not when it was imported from another module? This can be achieved using the __name__ attribute of the module.

Using a module’s __name__

#!/usr/bin/python

# Filename: using_name.py

if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module'

Output

                
$ python using_name.py
This program is being run by itself

$ python
>>> import using_name
I am being imported from another module
>>>

How It Works

Every Python module has it’s __name__ defined and if this is '__main__', it implies that the module is being run standalone by the user and we can do corresponding appropriate actions.


Question:

What does the if __name__ == "__main__": do?

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
while 1:
lock
.acquire()
time
.sleep(sleeptime)
lock
.release()
time
.sleep(sleeptime)
if __name__ == "__main__":
lock
= thread.allocate_lock()
thread
.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread
.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

Answer:

When the Python interpreter reads a source file, it executes all of the code found in it.

Before executing the code, it will define a few special variables. For example, if the python interpreter is running that module (the source file) as the main program, it sets the special __name__ variable to have a value "__main__". If this file is being imported from another module, __name__ will be set to the module’s name.

In the case of your script, let’s assume that it’s executing as the main function, e.g. you said something like

python threading_example.py

on the command line. After setting up the special variables, it will execute the import statement and load those modules. It will then evaluate the def block, creating a function object and creating a variable called myfunction that points to the function object. It will then read the if statement and see that __name__ does equal "__main__", so it will execute the block shown there.

One reason for doing this is that sometimes you write a module (a .py file) where it can be executed directly. Alternatively, it can also be imported and used in another module. By doing the main check, you can have that code only execute when you want to run the module as a program and not have it execute when someone just wants to import your module and call your functions themselves.

Samsung announces Connect Tag tracker that uses cellular IoT tech to help you find people and things

There is no shortage of little portable tracker devices that you can attach to your keys or your dog to ensure you never lose the things that matter most. But Samsung has today announced the Samsung Connect Tag, one of the first mobile consumer products that uses the fledgling narrowband IoT (NB-IoT) standard to connect devices.

For the uninitiated, NB-IoT licenses small amounts of LTE cellular spectrum to carry data for low-bandwidth devices. NB-IoT offers many benefits, including strong coverage, greater power efficiency (to preserve batteries), support for many devices, and relatively low operational costs. As its name suggests, it was very much designed with the internet of things in mind, and moving forward it will likely be used to connect myriad IoT contraptions, from smart trash cans to parking bay sensors.

At just 4.21 centimeters wide and 1.19 centimeters thick, the Samsung Connect Tag is fairly small and sports an embedded SIM (eSIM), which is basically a non-removable, programmable “virtual” SIM that consumes less space and doesn’t require the user to install a physical card.

As with similar trackers on the market, the device can be put to any number of uses, such as finding lost keys or giving parents peace of mind when their kid is out and about. The Connect Tag works with GPS, Wi-Fi-based positioning (WPS), and Cell ID (CID) to identify location data indoors and outdoors.

Above: Samsung Connect Tag

Building on Samsung’s push into the broader IoT realm, the Connect Tag works in conjunction with Samsung’s SmartThings Hub and the Samsung Connect mobile app so users can control and configure things remotely, while being able to integrate the tracker with other connected devices. For example, a user could set up a geo-fence zone for their home so that lights turn on automatically when the Connect Tag comes within a pre-defined perimeter. Alternatively, it could be used to notify a parent when their child arrives at school.

Though similar features and functionality already exist in other products, Samsung is touting the NB-IoT element as a key selling point. While it offers cellular connectivity for constantly tracking a specific person or product, it also promises “up to” seven days on a single charge, which is pretty good. However, we will reserve judgement until we can test one of these devices out for ourselves.

A number of companies have raised big VC funding for mobile tracking contraptions, including San Mateo-based Tile and Santa Barbara’s TrackR. Earlier this year, New York-headquartered Lynq announced a $2 million round of funding for a tracker that lets you find anyone in a radius of up to five miles. This tracker sidesteps Bluetooth, maps, Wi-Fi, and cell networks with a decentralized peer-to-peer (P2P) network that uses a mix of radio frequencies, a custom antenna, and a long-range low-powered chip.

Put simply, there is big demand for tracker devices, and it’s a market that Samsung is now looking to infiltrate. The company is debuting the Connect Tag at its developer conference in San Francisco later this week. But the device will first go on sale in Korea before expanding to “select countries” at a later date. Samsung hasn’t given any indication of price or launch dates.

Cellular NarrowBand IOT

NarrowBand IoT (NB-IoT) is a Low Power Wide Area Network (LPWAN) radio technology standard developed to enable a wide range of devices and services to be connected using cellular telecommunications bands. NB-IoT is a narrowband radio technology designed for the Internet of Things (IoT) and is one of a range of Mobile IoT (MIoT) technologies standardized by the 3rd Generation Partnership Project (3GPP). Other 3GPP IoT technologies include eMTC (enhanced Machine-Type Communication) and EC-GSM-IoT. The NB-IoT specification was frozen at Release 13 of the 3GPP specification (LTE-Advanced Pro), in June 2016.

NB-IoT focuses specifically on indoor coverage, low cost, long battery life, and enabling a large number of connected devices. The NB-IoT technology is deployed “in-band” in spectrum allocated to Long Term Evolution (LTE) – using resource blocks within a normal LTE carrier, or in the unused resource blocks within a LTE carrier’s guard-band – or “standalone” for deployments in dedicated spectrum. It is also suitable for the re-farming of GSM spectrum.

LTE Cat 1 LTE Cat 0 LTE Cat M1(eMTC) LTE Cat NB1(NB-IoT) EC-GSM-IoT
3GPP Release Release 8 Release 12 Release 13 Release 13 Release 13
Downlink Peak Rate 10 Mbit/s 1 Mbit/s 1 Mbit/s 250 kbit/s 474 kbit/s (EDGE)2 Mbit/s (EGPRS2B)
Uplink Peak Rate 5 Mbit/s 1 Mbit/s 1 Mbit/s 250 kbit/s (multi-tone)20 kbit/s (single-tone) 474 kbit/s (EDGE)2 Mbit/s (EGPRS2B)
Latency 50-100ms not deployed 10ms-15ms 1.6s-10s 700ms-2s
Number of Antennas 2 1 1 1 1-2
Duplex Mode Full Duplex Full or Half Duplex Full or Half Duplex Half Duplex Half Duplex
Device Receive Bandwidth 1.08 – 18 MHz 1.08 – 18 MHz 1.08 MHz 180 kHz 200 kHz
Receiver Chains 2 (MIMO) 1 (SISO) 1 (SISO) 1 (SISO) 1-2
Device Transmit Power 23 dBm 23 dBm 20 / 23 dBm 20 / 23 dBm 23 / 33 dBm

Sources:

  • Preliminary specification (Source: 3GPP)
  • 3GPP TS45.001

See also

Enabling Simultaneous AP and Managed Mode WiFi on Raspberry Pi Zero W

Personal note: Running both an access point and a client configuration on the same network adapter (i.e., simultaneous Client/AP mode) requires support for so-called virtual interfaces. Whether a certain Wifi hardware and driver combo supports virtual interfaces and in which configurations can be found out by looking at iw list output (look for AP and managed together under valid interface combinations).

People have said Atheros based wifi adapter -(e.g., TP-LINK TL-WN722N) is capable of doing such. The on-board wifi chip on Raspberry Pi isn’t, as I verified. Below is the actual output.

///////////////////////////////////////////////////////////////////////////////////////

valid interface combinations:
* #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
total <= 3, #channels <= 1
* #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
total <= 4, #channels <= 1

///////////////////////////////////////////////////////////////////////////////////////

After looking around a bit online, I found several people who claimed to have gotten this working, as well as posts saying it should work, based on the chipset. Despite my best efforts, I was unable to get any of those tutorials to work reliably on their own. By combining some information garnered from each one, along with some trial and error, I was finally able to get AP/Manged mode working, as described below.

Prerequisites

This tutorial assumes you’ve already created a bootable MicroSD card running the latest Raspbian Stretch image and have some way of accessing Linux, whether via serial interface, or a monitor and keyboard. If you haven’t, a couple of great resources I found online are:

  • Raspberry Pi Zero W “headless” Setup – This great tutorial walks you through getting WiFi client mode enabled on your RPi Zero W, without need for an attached monitor or keyboard. You will need a way to modify the contents of the MicroSD card’s filesystem, such as a Linux machine, Chromebook with crouton, or VM. There are also ways to do this from Windows, but I’ll leave that as an exercise for the reader.
  • Raspberry Pi Zero OTG Mode – Another awesome tutorial, via GitHub gist, which explains how to enable OTG / USB Gadget mode on the RPi Zero / Zero W. OTG mode lets you both power and communicate with the RPi Zero W as a virtual serial device, ethernet device, or mass storage device, among other things, with nothing more than a standard (read: non-OTG) USB cable. I used this to directly access the Raspbian Linux terminal via USB while trying to tweak the WiFi settings so that I wouldn’t drop my ssh session from headless mode.

Adding Udev Rule To Add A Virtual AP Device At Boot Time

Before we can operate our access point, we need a device allocated for it, similar to how systemd allocates a wlan0 device at boot time. On the build of Raspbian Stretch I’m using, only wlan0 is available automatically. We create a file caled /etc/udev/rules.d/70-persistent-net.rules which contains the following:

SUBSYSTEM=="ieee80211", ACTION=="add|change", ATTR{macaddress}=="b8:27:eb:ff:ff:ff", KERNEL=="phy0", \
  RUN+="/sbin/iw phy phy0 interface add ap0 type __ap", \
  RUN+="/bin/ip link set ap0 address b8:27:eb:ff:ff:ff"

Note that you must replace both MAC addresses above with that of your own RPi. You can find yours in various ways, such as from your router’s client list, or from the RPi’s command line via iw dev:

pi@raspberrypi:~$ iw dev
phy#0
        Unnamed/non-netdev interface
                wdev 0x4
                addr ba:27:eb:07:28:1f
                type P2P-device
                txpower 31.00 dBm
        Interface wlan0
                ifindex 2
                wdev 0x1
                addr b8:27:eb:ff:ff:ff
                ssid <YOUR HOME SSID> 
                type managed
                channel 6 (2437 MHz), width: 20 MHz, center1: 2437 MHz
                txpower 31.00 dBm

A number of tutorials I found claimed that the address for the virtual AP must be different from the primary MAC address. I found there to be no difference in behavior, but you should be able to change the last byte, for example, to give your client and AP different MACs.

The device we created above is called ap0. We will refer to this elsewhere, so if you decide to change the name, make sure to use the new name everywhere else I reference it, or things won’t work correctly.

Installing Dnsmasq and Hostapd

  • Dnsmasq – This program has extensive features, but for our purposes we are using it as a DHCP server for our WiFi AP.
  • Hostapd – This program defines our AP’s physical operation based on driver configuration.

Installing these is an easy affair:

$ sudo apt-get install dnsmasq hostapd

Wait awhile, and this process should complete. The install process may automatically start the dnsmasq.service in systemd right after installation and it will probably fail, since ap0 does not exist until we reboot. Disregard this for now.

Next, we need to modify 3 files. First we modify /etc/dnsmasq.conf by adding the following lines at the end of the file:

interface=lo,ap0
no-dhcp-interface=lo,wlan0
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=192.168.10.50,192.168.10.150,12h

Once again, notice we reference ap0 above, so use your device name here if you changed it earlier. I’ve added Google’s DNS server IP here (8.8.8.8) but feel free to use one from your router/ISP/or whatever. I’ve also made the assumption that our DHCP server will give out addresses on the 192.168.10.0/24 subnet, ranging from .50 to .150. You can substiute your own subnet here, but be sure to remember it for later, as it should match the static IP we assign your AP. The 12 hour lease time can also be arbitrarily changed to suit your needs.

Next, we need to modify the file at /etc/hostapd/hostapd.conf. I found many different parameters that can go in here, but this is what worked for me. Feel free to experiment further by poking around online. Lets do this for now:

ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
interface=ap0
driver=nl80211
ssid=YourApNameHere
hw_mode=g
channel=11
wmm_enabled=0
macaddr_acl=0
auth_algs=1
wpa=2
wpa_passphrase=YourPassPhraseHere
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=CCMP

A couple things to note here:

  1. Replace YourApNameHere and YourPassPhraseHere with the SSID and Passphrase you wish to use.
  2. I read multiple sources claiming that the channel you use here must match the channel that your wlan0 iterface is using for its WiFi connection, as reported by iw dev. In my testing, it looks like the RPi’s AP will dynamically change channels to match whatever channel the wlan0 interface is currently using. I watched this happen in real time by rebooting the WiFi AP the RPi was using, forcing it to roam and switch to another AP in my house. In the process, wlan0 switched from channel 11 to channel 6, and ap0 did the same, without losing connectivity.

Finally, we modify /etc/default/hostapd like so:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

This tells the hostpad daemon to use our new conf file. (To be honest, I’m not sure if this matters since we will be launching hostapd manually and pointing to the proper config file, but it shouldn’t hurt anything.)

Modify Our Interfaces File

Next, we need to define our WiFi network interfaces, both for our managed access (wlan0) and for our access point (ap0). We will also use wpa_supplicant to assist with connecting to WPA-encrypted WiFi networks. If you followed the “headless” bring-up tutorial I mentioned in the prereqs, you will have already touched both of the following files and configured wlan0 as required. In that case, we’ll be adding a static IP definition for ap0. First, we modify /etc/wpa_supplicant/wpa_supplicant.conf as so:

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="YourSSID1"
    psk="YourPassphrase1"
    id_str="AP1"
}

network={
    ssid="YourSSID2"
    psk="YourPassphrase2"
    id_str="AP2"
}

Again, you should replace the SSIDs and Passphrases above with your own. You aren’t required to name multiple SSIDs here, but if you add more, the RPi can roam between networks if configured correctly, as we will do below. The id_str field can be used as a quick reference name in our interfaces file. You should also change the country code to whatever is appropriate for your region.

Next, we modify /etc/network/interfaces to support our new AP:

# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
auto ap0
auto wlan0
iface lo inet loopback

allow-hotplug ap0
iface ap0 inet static
    address 192.168.10.1
    netmask 255.255.255.0
    hostapd /etc/hostapd/hostapd.conf

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface AP1 inet dhcp
iface AP2 inet dhcp

As you can see, we want both ap0 and wlan0 to start up automatically, with ap0 defined to have a static IP of 192.168.10.1 on the 192.168.10.0/24 subnet. Recall, the DHCP address range we defined in /etc/dnsmasq.conf matched this subnet. Adjust accordingly if you made changes. We also reference our hostapd config file here, to direct the AP configuration for ap0.

For wlan0, we start it using manual mode and point it to our /etc/wpa_supplicant/wpa_supplicant.conf file for our WiFi network definitions. The wpa-roam designator will allow the interface to move freely between our defined networks. Finally, the last two lines use our friendly names from wpa_supplicant.conf to refer to our available networks, and indicate this interface should use DHCP supplied by those APs to assign an address to wlan0. Please note the order here: ap0 must come up before wlan0, or they won’t both work at the same time.

We’re Done! Or Are We…

At this point, I expect everything to work after a reboot. Instead, I end up with wlan0 UP and ap0 DOWN (or vice-versa) when checking via ip addr, and dmesg indicates some errors in the Broadcom driver. After some tinkering, I discovered the following sequence of commands after a reboot would get both interfaces up and working simultaneously, like we wanted all along:

$ sudo ifdown --force wlan0
$ sudo ifdown --force ap0
$ sudo ifup ap0
$ sudo ifup wlan0

I had to add --force because sometimes hostapd would complain about having a lock on wlan0 and fail to proceed, so it ensures we get what we want. After bringing down both interfaces, again, with ap0 going first, followed by wlan0, they should both come up:

pi@raspberrypi:~$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b8:27:eb:ff:ff:ff brd ff:ff:ff:ff:ff:ff
    inet 192.168.43.37/24 brd 192.168.43.255 scope global wlan0
       valid_lft forever preferred_lft forever
    inet6 fe80::ba27:ebff:fede:3a79/64 scope link
       valid_lft forever preferred_lft forever
3: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b8:27:eb:ff:ff:ff brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.1/24 brd 192.168.10.255 scope global ap0
       valid_lft forever preferred_lft forever
    inet6 fe80::ba27:ebff:fede:3a79/64 scope link
       valid_lft forever preferred_lft forever

Great! But what about bridging traffic between my AP and client sides to allow a device to access the internet through my RPi? Let’s do that:

$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE
$ sudo systemctl restart dnsmasq

Here, we enable ip forwarding to allow packets to be forwarded between interfaces, and we add a postrouting rule to IP tables which routes all packets from the AP-side interface to the client-side interface (where MASQUERADE is necessary, since the IP is dynamic and undefined until wlan0 connects to an AP). Finally, we restart dnsmasq for good measure, since we previously brought down ap0 with ifdown.

At this point, we should be able to connect a device to our Raspberry Pi Zero W’s AP SSID, while we also have our RPi connect to another access point for internet access, and we should be able to access the internet from that device through our RPi. Only one thing left to do…

Automate The Workaround

Try as I might to debug the issues I was having before manaully reseting the interfaces, I was unable to get the RPi to simply boot up working correctly. So, I decided to script the steps to “fix” everything and set them to run as a root cron job with a 30s delay… (Yes, I know this is horrible practice, but I’m open to better suggestions.) I intially tried setting up a systemd service to call my script instead of cron with a delay, but it didn’t seem to work or ran at the wrong time, requiring manual intervention.

Here’s the script in it’s entirety:

pi@raspberrypi:~$ cat ./start-ap-managed-wifi.sh
#!/bin/bash
sleep 30
sudo ifdown --force wlan0 && sudo ifdown --force ap0 && sudo ifup ap0 && sudo ifup wlan0
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE
sudo systemctl restart dnsmasq

I simply left the file in my default “pi” user’s home directory, but you can move it someplace more appropriate, such as /sbin. I then added a cron job like so:

$ sudo crontab -e

And in there I added the line:

@reboot /home/pi/start-ap-managed-wifi.sh

This causes the script to run at every reboot. In testing, I foud the RPi Zero W boots in under 20s. Systemd runs the cron service somewhere in that range of time, which eventually runs the script above. To be safe, you can change the 30s delay to something longer, but I found this to be pretty reliable.

Now, after every reboot, even though ap0 and wlan0 don’t initally play well together, the cron job kicks off my script after 30s and magically fixes everything. We have AP and Managed mode running at the same time, and we’re bridging traffic between the interfaces to allow for internet sharing through the Raspberry Pi Zero W.

Special Thanks

The following links were pretty instrumental in getting things moving in the right direction, so please check them out:

Please comment below if this helped you, or if you have any suggestions for improvements!

Personal note: You should disable dhcpcd at boot by running
sudo update-rc.d dhcpcd disable
However, the ethernet would be disabled as well at boot. This has been tested on Raspberry Pi 3 model B.

 

朱啸虎复盘滴滴成长秘史:早期投他们 是觉得他们非常适合做地推

腾讯投资部把所有的公司看了一遍之后,第一选择是滴滴。

观望易到、摇摇、快的之后,为何是滴滴?

我们关注出行领域时间很久了。美国投「优步」的Benchmark和我们关系很好,当初还跟我们说,在美国投了一家比较好的公司,叫优步,发展很快。

于是我们就找类似的公司,当时还在早期。最早是「易到」,易到比滴滴早两年时间。易到团队也很成功,在杭州创业,现在公司已经卖掉了。

当初他们从阿里挖了一个 B2B 的中供的销售人员,过去做地推。我们看了三个礼拜,但数据不行。而且他们严格对标优步,在中国做专车。

当时(五六年前)中国没有人说专车。不像美国,美国大家都知道专车,在美国有一百多的历史。

所以他们当时专门招人做地推,办公楼从上往下扫,向所有的小老板介绍,说你应该有更好的出租车。进度非常慢,每个礼拜的实际达成业绩是预测的10%左右。

当时智能手机没有普及,所以还需要给司机送智能手机。虽然才一千块钱,但是也是成本,同时还要教育用户获取市场。

我们看了三期,觉得易到不对,没有投。

后来等了两年时间,出来了「摇摇」。我们和他们 CTO 关系很好,知道 CTO 和 CEO 有矛盾——CTO 一直不坚定。他是谷歌非常好的产品经理,但一直没有下定决心加入这个公司,一直在「半兼职」,也对 CEO 一直有很多抱怨。

这家公司一直在摇摆做专车还是出租车,产品市场一直在晃。而且 CEO 的互联网思维比较弱,该产品要先注册,先充值才能用,这样转化率很差。后来他们拿了红杉 300 万美金的投资。

再后来是「快的」,快的是陈伟星孵化的,陈伟星是一个很优秀的创业者。这是他孵化的项目,但他不是全职做 CEO。所以这个公司是没有 CEO 的,也比较难投。

当时我不认识程维。我在微博上搜滴滴打车,然后找到程维私信他。他是唯一一个专门做出租车领域的。他想的很清楚:占领市场份额 80%以上才会做专车。再加上他本身的阿里背景,非常擅长做地推,而且战略非常清晰,于是我们很快投了滴滴。

滴滴的迅速崛起之路,「快滴」大战

投了半年之后,我们把摇摇干掉了,这时摇摇依然在出租车和专车之间摇摆。那年冬天北京下了3场雪,每下一场雪,滴滴的数据就翻一番。

开年之后开两会,马化腾到北京找程维吃饭,他亲自找程维聊,以投资人的名义。当时滴滴还很小,每天几千单。腾讯投资部把所有的公司看了一遍之后,第一选择是滴滴,如果滴滴不让腾讯投,他们肯定会投第二家。

当时阿里已经给了快的一笔钱,滴滴去找阿里很尴尬,拿腾讯的钱也非常有顾虑。当时也很被动,最后还是决定拿了腾讯的钱。

拿了腾讯的钱之后发生了很戏剧化的事情——那年春节腾讯的微信红包火了。然而过完春节,红包热过了,微信支付没有用户了。微信支付就找到滴滴合作,而且腾讯付钱做补贴。当时滴滴很客气,预算 800 万做 3 个礼拜——腾讯觉得太少,给了 1500 万。结果上线半天 1500 万没有了,但是效果非常好。

当时很多朋友都是滴滴用户,但是不愿意绑卡,因为绑卡风险太大。为了 10 块钱的补贴,都去绑卡了,这里面还包括一些投行人士、证券分析师。

活动上了两个礼拜之后,支付宝醒悟过来,觉得这威胁很大,于是最后一个礼拜支付宝追进了。我们三个礼拜做完之后准备停了,当时远远超过了 1500 万的预算。但是腾讯觉得 10 块钱买一个绑卡用户很合算。

后来滴滴停了一个周末两天时间,但是支付宝没有停。我们看到数据发生了变化,到了星期天晚上,三七开。如果继续停,再一个礼拜肯定就翻盘了。所以星期天晚上我们召开了电话会议,商量要不要继续跟进。结果还是跟进,腾讯继续支持,方案改成了资金滴滴出一半,腾讯出一半。

到第二天凌晨,继续补贴的方案上线了。阿里永远比滴滴多一块钱,双方像打游戏一样,一直是动态调整的。后来又打了三四个星期,最后不是看谁的补贴多,而是看谁的服务器不 down 掉——每次下班高峰期都进不去。

腾讯派了 50 个工程师到滴滴解决优化问题。工程师当时都是做偷菜的人,只有偷菜的人才见过这么高的并发量。50 个工程师通宵干了七天七夜,非常给力。同样的,支付宝团队也在帮快的优化。

当年有很多经验——要把什么样服务停掉?如何专注在核心能力上?所以当时把周边的业务都降级,用来保证核心业务,当时滴滴后台系统全部重新升级。

后来马云出面喊停,当时双方信任度很差,互相的往下降,所以最后退出很讲究,退得也非常的不容易。那个时候已经开始谈合并了,因为大家觉得补贴太凶狠了,大家干也干得差不多了。

「三国盛世」下的融资大战

上海三分天下,滴滴、快的、大黄蜂,一上来全部打补贴战。当时大黄蜂在两个方面兜售,找滴滴和快的问他们要不要,一开始双方出价,但是价格太离谱了。

后来者更希望靠全补贴打透一个市场,靠补贴能把上海拿下来,找投资人继续拿钱。

当时滴滴放话给阿里说,我们放弃收购大黄蜂,我们可以签字不要大黄蜂,大家要什么价格自己去谈。

当时柳青代表高盛,想投资滴滴,但是希望滴滴和快的合并之后再投资。当时滴滴的市场份额大,我们希望在七三比较好。结果后面继续打,双方相互阻击融资。

当时,滴滴要融 C 轮很难,拿了腾讯的钱融资非常难,于是去美国融资。每见一个投资人,Joe 蔡就打电话过去,说不许投。从东海回到西安的时候,我们约了好几个投资者,但是阿里马上打电话说不能投。

当时阿里马上要上市,说,不投滴滴我给你分配阿里股份。当时非常痛苦。本来一个投资人已经说好要投的,后来黄了。甚至马云亲自和投资基金见面,达成了共识,最后没有投滴滴。

回来之后我们找到吴敬阳,找到中信产业基金。当时他们和马云说好,不会投滴滴和快的。但没有想到的是,他们看到数据之后觉得滴滴相当不错。以当时情况来说,这太不容易了。在这之后就比较顺了。

融了 C 轮之后,柳青加入,我们也没有想到。因为柳青和程维接触了很多次,柳青一直表示想合并之后投,这可以理解。没想到程维已经说服柳青加入滴滴,我们自己都没有想到,程维确实敢想敢做。

柳青入局之后,滴滴的融资进展非常顺利,所有投资人见了滴滴和快的全部投了滴滴。后面快的的融资进行得很困难。最后,马云亲自打电话给孙正义说,要支持快的,孙正义给了快的 7 个亿,后面还有 3 亿美金在犹豫要不要投。

三国归晋,滴滴开战优步

最后还是合并了。合并定下来之后非常快,可能在深圳谈了两三天合并,条款谈了一个多礼拜,就达成了共识。滴滴和快的合并之后,在国内就剩下了优步,易到等都比较小了。

我们投滴滴的时候去旧金山见过优步的创始人。没有一家美国公司在中国成功过,最成功的是当年谷歌投了百度 5%的股份,赚了很多钱。其实他可以参考这个案例,投滴滴 5%的股份。但他说 5%太少了,要投 40%,40%怎么赚钱?

他下面的人都认可,但是他不愿意,就打了一仗。优步在中国烧了 20 亿美金,每个月都亏,很多钱被骗补贴骗走了。补贴的效率很差,在中国推广产品有很多特殊性。

最后他的压力非常大。优步不像滴滴。滴滴的投资人可以在过程中随时退出,还欢迎早期投资人卖股份;而优步不让投资人卖股份,最后就被赶下去就是这个原因。优步的投资人投优步比我们早一两年,到现在一分钱都没有卖掉。肯定有卖股份这个需求,但是他不支持。

优步亏损得很厉害,在中国烧了 20 亿美金。投资人不愿意了,给他很大的压力,让他们必须退出中国。

于是他们主动找上了滴滴。我们虽然可以把它打死,但是代价很高,合并的损失会更少一点。最近优步出了很多问题,给了滴滴很好的机会。这可能成为中国第一个案例,中国的模式到美国去投资。

滴滴和优步有一点不同的策略:我们在海外扩张都是选择当地的合作伙伴。中国人英语水平不行,达不到在当地工作的交流水平,本地人去海外很难。于是我们把技术、运营策略输出给他们,这非常好。

当时第一个投了 Lyft。原因很简单,我们不能让优步在美国赚钱。一旦优步在美国赚钱,他们肯定拿全球的利润来补贴中国区的发展。通过 Lyft 骚扰优步使其不能在本土赚钱,后来目的达到了。Lyft 在美国市场的地位逐步上升,而美国的优步基本还赚不到钱。

所以总体来看确实滴滴每一步都惊心动魄,每一步的运气很好,我们没有犯错误,都是对手犯错误,尤其是优步犯了很多错。

如何看 CEO 和投资人的关系很重要。不能忽视投资人的需求,最后一旦出问题,矛盾会激烈地爆发出来。优步在单一项上赚了 80 亿美金,这么赚钱的项目,投资人还是把 CEO 赶走了,可见矛盾有多深。这是非常有意思的案例。

滴滴的未来&滴滴团队的闪光点

在朱啸虎见面会现场,还有一个嘉宾问答环节。在听完朱啸虎的叙述之后,参会企业的CEO或者创始人们各自提出了自己想了解、学习的一些困惑。以下内容已经过整理汇总。

Q1:滴滴等网约车,在相当一段时间内被政府政策限制,当时融资怎么解决这个问题?现在滴滴认为自己的边界在哪里?滴滴存在哪些风险?

朱啸虎:中国政府都这样,先看看,先放一放,行业稳定之后出监管政策,包括新闻、P2P、游戏、支付等等,投资人对这方面不担心。

现在出行相关的都是滴滴核心业务,比如二手车、新车、车加油、车后市场都是滴滴相关业务,包括驾驶、人工智能都是相关的业务。不一定是投资,绝大部分是自营。

风险永远存在,比如团队,在无人驾驶方面是否会落后。

Q2:怎么看共享汽车?

朱啸虎:在农村有市场,比如电动汽车,很多农民花几十块钱开一天,从农村开到乡里。但在城市很难做,为什么?停车费,在农村停车免费,共享单车不用停车费。

所以这需求是有,关键是守不住,而且还是非常小的市场。你看黄包车都守不住就知道了。

现在携程的微导游很厉害,网络很强大,社区很活跃,游客自己会互相分享。而且他们在尝试商业化,转化率非常高。关键是游客内部之间会分享,这是好玩的事情。它从入口端就留住了。但共享汽车没法打,短期一两年内可以做,长期比较难。

做小而美的公司很好,千万不要想太多,90%以上的公司是小而美的公司。

做小而美的公司,先把基本的东西想好。不能想太多,想太多死得快。小而美现在很滋润,但想做入口就可能会死得很惨。比如我们见过一家在智能家居做入口的,很难,我们不敢投,产业入口要烧很多钱。

Q3:滴滴团队带着成长的核心人才是哪些?程维最初团队是如何过渡到后来的人才结构?

朱啸虎:当年就靠地推,确实很辛苦。北京冬天凌晨 4 点钟他们起来找出租车——早上 4 点钟是出租车司机吃早饭的时候,是政府供应的特价早餐,那里容易找到出租车司机。当时快的打不过滴滴。支付宝派人去北京,呆了一天就回杭州了。

滴滴早期大部分是做地推的,今天大部分是技术。我们早期投他们,是觉得他们非常适合做地推。当时必须在两分钟之内全部搞定,比如话术,这里有一套非常好的程序。

程维在组织结构调整上非常有水平。确实在四五年中,整个公司的体系有巨大的变化,他初期的还人在,但是要找更好的岗位。阿里也是如此,阿里也有早期的人。

Q4:当年的程维可能不是最优秀的,什么原因决定你投他?你说到程维的成长,作为CEO他有什么好的学习方式?

朱啸虎:我觉得他是唯一在那个行业想清楚事情的,就想做出租车。

当时所有人没有想清楚为什么做出租车。当年A轮很困难,投资人不理解出租车行业,因为出租车行业确实很辛苦,出租车每天工作十几个小时每个月才赚四五千块。从出租车司机上身上赚钱是不可能的事。

但是他想清楚了出租车司机是入口。创业企业千万不要教育市场,比如起码要在出租车圈过来之后再做升级,升级是相对很靠谱的一件事。

程维的学习能力很强,心态开放,他向任何一个投资人、合作伙伴学习。千万不要说谎和隐藏,任何数据和信息开放,这样才能尽快地发现问题去纠错。

创始人如果和我说,这个很好、很放心,肯定不行;如果他说这个公司这个问题、那个问题,那这种创始人比较有机会。

A good Express JS crash course

 

Express.js, or simply Express, is a web application framework for Node.js, released as free and open-source software under the MIT License. It is designed for building web applications and APIs. It is in fact the standard server framework for Node.js.

The original author, TJ Holowaychuk, described it as a Sinatra-inspired server, meaning that it is relatively minimal with many features available as plugins. Express is the backend part of the MEAN stack, together with MongoDB database and AngularJS frontend framework.